Java多线程初步--总结(一)

2014-11-24 03:19:31 · 作者: · 浏览: 5

1、线程简介

os当中的多线程分为用户级线程和内核级线程。

①用户级线程,由对应的进程创建,一个进程可以创建一个或多个线程,当进程获得处理机时,这些线程并发的执行,将这个时间片分配为更小的时间片,进而并发的执行。用户级线程对于系统内核是透明的,内核只能看到进程的执行,而不知道进程进一步分为了多个线程。也正是如此用户级线程无法享受到多核的好处。如果内核是单线程的,那么任何一个用户级线程若执行阻塞系统调用就会引起整个进程阻塞,即使还有其他线程可以在应用程序内运行。

②内核级线程,内核级线程对于系统内核是可见的,有系统内核调度各个线程,内核级线程可以享受到多核的好处。但是创建比较耗费资源。、

在java当中实现的是用户级线程。java中涉及到线程的一个接口是Runnable,实现了这个接口的类是Thread。Runnable当中只有一个run()方法,而在Thread类当中除了实现了run()方法外还实现了更多的方法,其中比较重要的方法就是start()方法。

start()方法和run()方法的主要区别就是run()方式就是执行线程,而start()方法是开启线程,其中包括了执行线程,但是在执行线程之前,还要做其他的工作。

注意:如果要实现线程的并发执行,不要直接调用run()方法,而要调用start()方法。这样才能保证,不同的线程并发的执行。而run()方法当中的内容便是线程执行时所执行的内容。

2、Thread类

在java当中Thread类共有八个构造函数,如下:

Thread()

分配新的 Thread 对象。

Thread(Runnable target)

分配新的 Thread 对象。

Thread(Runnable target, String name)

分配新的 Thread 对象。

Thread(String name)

分配新的 Thread 对象。

Thread(ThreadGroup group, Runnable target)

分配新的 Thread 对象。

Thread(ThreadGroup group, Runnable target,String name)

分配新的 Thread 对象,以便将 target 作为其运行对象,将指定的 name 作为其名称,并作为 group 所引用的线程组的一员。

Thread(ThreadGroup group, Runnable target,String name, long stackSize)

分配新的 Thread 对象,以便将 target 作为其运行对象,将指定的 name 作为其名称,作为 group 所引用的线程组的一员,并具有指定的堆栈尺寸。

Thread(ThreadGroup group, String name)

分配新的 Thread 对象。

从这八个构造函数,可以看出Thread方法和Runnable接口是密切关联的。其中Runnable target是实现了Runnable接口的类或者是接口,而这个接口当中复写了run()方法,因此Runnabletarget在这里的主要的作用是使用复写了的run()方法。

String name,参数主要用于设置线程的名称。如果不对线程的名称进行显示的设置,线程的名称为Thread-N.其中N为不重复的整数。而设置线程的名称主要有两种方式,一种便是在构造函数当中设置,另外一种便是在start()方法之前使用setName()方式进行设置。

ThreadGroup group主要用于设置线程组。如果不进行显示的设置,默认所有的线程都再一个组当中。

long satckSize线程栈的大小。这个值一般为cpu页面值大小的整数倍。每个线程都有各自的线程栈,用户存放运行当中的变量。

3、通过Runnable接口创建线程

通过Runnable接口创建线程主要有两个步骤组成

①将实现了Runnable接口的类进行实例化

②建立Thread对象,并把第一步当中实例化的类做为Thread构造函数的参数。

这个过程可以从Thread类的构造方法当中看出来。

4、与人有生老病死一样,线程也同样要经历开始(等待)、运行、挂起和停止四种不同的状态。这四种状态都可以通过Thread类中的方法进行控制。下面给出了Thread类中和这四种状态相关的方法。

1. // 开始线程

2. public void start( );

3. public void run( );

4.

5. // 挂起和唤醒线程

6. public void resume( ); // 不建议使用

7. public void suspend( ); // 不建议使用

8. public static void sleep(long millis);

9. public static void sleep(long millis, int nanos);

10.

11. // 终止线程

12. public void stop( ); // 不建议使用

13. public void interrupt( );

14.

15. // 得到线程状态

16. public boolean isAlive( );

17. public boolean isInterrupted( ); //测试线程是否已经中断。包括当先线程和其他线程

18. public static boolean interrupted( ); //测试当前线程是否已经中断。

19.

20. // join方法

21. public void join( ) throws InterruptedException;

关于为什么这三个方法不建议使用是因为在jdk当中已经将这三个方法标注为过期,也就是说在以后的jdk当中有可能取消这些方法。

\

\

\

5、join方法的理解

join方法的功能就是使异步执行的线程变成同步执行。就是说如果一个线程调用了join方法,那么这个线程必须执行完之后,其他线程成才能执行。也就是说,调用join方法的线程在run()方法执行完之后才能执行其他线程。

6、volatile关键字

volatile关键字用于声明简单类型变量,如int、float、boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。

在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。

volatile关键字的原理是在java memery当中的main memery和working memory,中只放一份数据的备份。就是说