Java之旅多线程学习(一)——线程的实现方式
2015-10-18 11:28
351 查看
在讲解线程之前,我们来看看什么是进程以及两者的区别。
程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
我们知道程序的执行不仅仅有单道程序设计同时也是存在多道程序设计的,多道程序设计就是可以处理多个程序的并发执行的,大大提高cpu的利用率,那么线程是什么呢?
线程,在网络或多用户环境下,一个服务器通常需要接收大量且不确定数量用户的并发请求,为每一个请求都创建一个进程显然是行不通的,——无论是从系统资源开销方面或是响应用户请求的效率方面来看。因此,操作系统中线程的概念便被引进了。线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,也是 CPU 调度的一个基本单位。
线程以及进程的出现都是为了解决并发的问题,只是层次不一样,进行是处理器这一层级的,而线程属于进程这个层级提供的抽象。线程是是进程的一个不同的执行路径,进程有自己独立的地址空间,而线程之间是没有的,拥有的是自己的堆栈和局部变量。并且是多个线程是可以并发执行的。
在单程序中,某一个时间点进行的处理只有一个,也就是执行的程序的主体只有一个。
此时书写:
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>public static void main(String[] args) {
// 此时是单线程
for (int i = 0; i < 1000; i++) {
System.out.println("Good");
}
}
</strong></span>
执行相应的程序的时候,至少会有一个线程开始操作,那么有操作的被称之为主线程,执行的操作是输出字符串“Good”。
新建一个线程MyThread继承Thread:
新启动的线程的操作写在了run方法里面,新线程启动后,才会调用run方法,同样run方法结束,线程也会结束,但是这样是无法运行run的,因为运行run的前提是线程必须启动。
新建一个类,在主程序中启动:
程序的详解:调用新启动的线程MyThread t = new MyThread();run方法,线程启动后就会自动调用run方法,t.start();表示的是主线程启动新线程,start是thread的方法,调用时则会调用新线程。java程序就会在背后进行新线程的处理;而不是run方法,可以使用run,此时不会启动新的线程,真正开启新的线程的方法是start方法。
其中调用start方法的时候执行了两个操作;启动新线程,调用run方法。
此时我们说说并行和并发的区别:
并发:当有一个以上的线程在操作时,若计算机只有一个中央处理器,根本不可能同时执行一个以上的处理,输出字符串的交替输出实际上是一个执行一会后再执行另一个,也就是说程序的执行像这样不断地切换有操作的过程,这种操作就称之为并发。
并行:如果是在有一个以上中央处理器的计算机跑的java执行处理系统,那么线程的执行可能是并行,而非并发。
如图:
![](https://img-blog.csdn.net/20151018112242026?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
Runnable接口是java.lang.Package里的接口,定义如下:
建立一个实现了Runnable接口的类:
在主程序的类中开启新的线程:
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>/**
* 测试多线程
*
* @param args
*/
public static void main(String[] args) {
new Thread(new Printer("good")).start(); // Printer("good")).start();
new Thread(new Printer("nice")).start();
}
</strong></span>
建立的是一个实现了Runnable的接口的类,将该实例传递给Thread的构造器,作为构造器的参数,调用start方法来启动线程。
当然也是可以分步进行的:
步骤是:先建立Printer类的实例,把它作为参数传递出去,再建立thread类的实例,此时调用该实例的start方法
小结:无论是thread类还是Runnable接口类,启动新线程的方法永远都是Thread方法的start类。
1. 进程VS线程
程序是什么?程序:在时间上严格有序的指令集合。它独占使用系统中的一切资源,包括CPU、内存、外设以及软件等等,没有其他竞争者同它争夺与共享。因此,在单CPU的计算机系统中,一段时间内只有一个程序在运行。程序独占了计算机的全部资源,不受外来影响。程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。
我们知道程序的执行不仅仅有单道程序设计同时也是存在多道程序设计的,多道程序设计就是可以处理多个程序的并发执行的,大大提高cpu的利用率,那么线程是什么呢?
线程,在网络或多用户环境下,一个服务器通常需要接收大量且不确定数量用户的并发请求,为每一个请求都创建一个进程显然是行不通的,——无论是从系统资源开销方面或是响应用户请求的效率方面来看。因此,操作系统中线程的概念便被引进了。线程,是进程的一部分,一个没有线程的进程可以被看作是单线程的。线程有时又被称为轻权进程或轻量级进程,也是 CPU 调度的一个基本单位。
线程以及进程的出现都是为了解决并发的问题,只是层次不一样,进行是处理器这一层级的,而线程属于进程这个层级提供的抽象。线程是是进程的一个不同的执行路径,进程有自己独立的地址空间,而线程之间是没有的,拥有的是自己的堆栈和局部变量。并且是多个线程是可以并发执行的。
2. 线程的实现方式
一般情况下,我们在解读程序的时候,通常都是追着处理流程跑:先执行某个语句,再执行某个语句,最后执行某个语句,看似是追踪流程实则是追踪线程。单线程程序(single threaded program)
如果程序的处理流程从头到尾就像一条线,则该程序为单线程程序,形象地说就是把程序的执行比作一条小河,虽然弯曲,但是连成的是一条线。在单程序中,某一个时间点进行的处理只有一个,也就是执行的程序的主体只有一个。
此时书写:
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>public static void main(String[] args) {
// 此时是单线程
for (int i = 0; i < 1000; i++) {
System.out.println("Good");
}
}
</strong></span>
执行相应的程序的时候,至少会有一个线程开始操作,那么有操作的被称之为主线程,执行的操作是输出字符串“Good”。
多线程程序(multithreaded program)
由一个线程以上所构成的程序称之为多线程。具体实现由两种方式:Thread和Runnable。线程启动--------Thread类子类实现
使用Thread的run和start方法来实现。因为必须在线程的某个位置启动新的线程才算是多线程,故而先new 一个线程。新建一个线程MyThread继承Thread:
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>/** * 新的线程启动类 * * @author LiXiaoNa * */ public class MyThread extends Thread { public void run() { for (int i = 0; i < 100; i++) { System.out.println("nice!"); } } } </strong></span>
新启动的线程的操作写在了run方法里面,新线程启动后,才会调用run方法,同样run方法结束,线程也会结束,但是这样是无法运行run的,因为运行run的前提是线程必须启动。
新建一个类,在主程序中启动:
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>/** * 测试多线程 * * @param args */ public static void main(String[] args) { MyThread t = new MyThread(); t.start(); // 此时是单线程 for (int i = 0; i < 1000; i++) { System.out.println("Good"); } } </strong></span>
程序的详解:调用新启动的线程MyThread t = new MyThread();run方法,线程启动后就会自动调用run方法,t.start();表示的是主线程启动新线程,start是thread的方法,调用时则会调用新线程。java程序就会在背后进行新线程的处理;而不是run方法,可以使用run,此时不会启动新的线程,真正开启新的线程的方法是start方法。
其中调用start方法的时候执行了两个操作;启动新线程,调用run方法。
此时我们说说并行和并发的区别:
并发:当有一个以上的线程在操作时,若计算机只有一个中央处理器,根本不可能同时执行一个以上的处理,输出字符串的交替输出实际上是一个执行一会后再执行另一个,也就是说程序的执行像这样不断地切换有操作的过程,这种操作就称之为并发。
并行:如果是在有一个以上中央处理器的计算机跑的java执行处理系统,那么线程的执行可能是并行,而非并发。
如图:
线程启动--------Runnable接口类的实现
实现了Runnable接口的类的实例以启动线程的方法。Runnable接口是java.lang.Package里的接口,定义如下:
建立一个实现了Runnable接口的类:
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>public class Printer implements Runnable { private String message; public Printer(String message) { this.message = message; } public void run() { for (int i = 0; i < 100; i++) { System.out.println(message); } } } </strong></span>
在主程序的类中开启新的线程:
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>/**
* 测试多线程
*
* @param args
*/
public static void main(String[] args) {
new Thread(new Printer("good")).start(); // Printer("good")).start();
new Thread(new Printer("nice")).start();
}
</strong></span>
建立的是一个实现了Runnable的接口的类,将该实例传递给Thread的构造器,作为构造器的参数,调用start方法来启动线程。
当然也是可以分步进行的:
步骤是:先建立Printer类的实例,把它作为参数传递出去,再建立thread类的实例,此时调用该实例的start方法
<span style="font-family:Microsoft YaHei;font-size:14px;"><strong>Printer printer=new Printer("good"); Thread thread=new Thread(printer); thread.start();</strong></span>
小结:无论是thread类还是Runnable接口类,启动新线程的方法永远都是Thread方法的start类。
3. 待续……
这是自己学习刚开始的一步,后面的学习还将继续~相关文章推荐
- MyBatis-Spring配置简单了解
- java jdbc笔记整理
- spring framework源码下载并导入eclipse
- EL表达式 (详解)
- java线程池的初步使用和探究
- JDBC-Java程序向mysql中插入数据的中文乱码
- Java的强制类型转换与隐式类型转换
- Java类加载原理解析
- HDU1036 Average is not Fast Enough!(java)
- JAVA中的代理技术(静态代理和动态代理)
- Java学习随笔2:Java复合赋值表达式的小问题
- LeetCode解题报告--Remove Element
- 在Eclipse中应该怎样去修改Android应用程序的包名(注意按步骤修改)
- java保存获取Web内容的文件
- java中的线程(三)——控制线程的几种简单的方法和线程同步
- java--通过DOM4J方式生成rss文件简单实例
- [jetty] lost connection with Eclipse , shutting down.
- Java学习随笔1:Java是值传递还是引用传递?
- I/O failure during classpath scanning in spring MVC
- Javassist介绍