JAVA 多线程实现(一)

2014-11-24 03:24:28 · 作者: · 浏览: 1

最简单的创建线程的方法
1 继承java.lang.Thread类
2 重写run方法
3 初始化该类实例
4 调用start方法

继承Thread类的方法,线程的生命周期JVM认为是从run方法的第一行开始,到run方法返回为止
run方法一旦返回,线程就死掉了。

在调用start方法的时候,start方法有可能在任何一个时间执行,这个过程是异步的,并不是立即执行。

start方法只是简单的通知JVM的排程器,告诉它,当前线程已经准备好了,应当尽早执行run方法。

一个睡眠的线程可以被其他线程所打断,这样,这个睡眠的线程就会抛出
InterruptedException异常。在捕获这个异常之后,user就可以处理一些情况。

实现Runnable接口来创建线程
1 某类实现java.lang.Runnable接口
2 重写run方法
3 使用Thread构造函数,将该类包装进去
4 实例化Thread类
5 调用start方法

interrupt()方法
中断一个线程的当前行为
interrupt只是简单的设置一个中断标志,告诉当前线程你应当被打断
sleep方法可以清除interrupt方法设定的标志。
如果在sleep方法调用之前就已经设置了中断的标志,那么sleep方法会立即抛出异常。

package cn.bj.brook.test;

public class MainRun {

/**
* @param args
*/
public static void main(String[] args) {
Thread t1 = new Thread(new T1());
Thread t2 = new Thread(new T2());
t1.start();
t2.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.interrupt();

}

}

class T1 implements Runnable{
@Override
public void run() {
while(true){
System.out.println("Thread 1 running");
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

class T2 implements Runnable{
@Override
public void run() {
while(true){
System.out.println("Thread 2 running");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
}

}
输出结果
Thread 1 running
Thread 2 running
Thread 1 running
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at cn.bj.brook.test.T1.run(MainRun.java:30)
at java.lang.Thread.run(Thread.java:619)
Thread 2 running
Thread 2 running
...

Thread.interrupted()方法返回当前调用线程的中断状态
和实例的isInterrupted()方法不一样,该静态方法自动将中断标志设为false。

能抛出InterruptedException异常的方法并不只有sleep()还有wait()方法
当wait()被打断的时候也会抛出这个异常。

让一个线程挂起的方法是使用睡眠,而让一个线程停止的方法是加入程序分支自然返回

守护线程,守护线程是这么一个线程,本身不做任何事情,就在后台空转,专门为别的线程
提供服务的线程。Java虚拟机不会负责守护线程的生死状态,一旦所有非守护线程退出,则
自动关闭。通过setDaemon方法来设置,设置为true了则称为守护线程。
守护线程不能阻止Java虚拟机退出。

线程的优先级
线程的优先级默认的是和创建它的线程的优先级是一样的。更改线程优先级的时候要注意不要超过
系统线程的优先级。注意,线程的优先级和操作系统和虚拟机是分不开的,java标准,线程的优先级
只是向虚拟机建议,所以,你编的程序不应当依赖于线程的优先级设置,即使没有优先级,你仍然
能够保证程序逻辑的正确性。

Java虚拟机里边的系统线程如下

main Java程序的入口线程,优先级是5,一般线程都是从此线程创建而来,所以优先级是5;
Finalizer 垃圾收集器线程,这个线程的优先级是8,以便垃圾收集器能够有更多的机会得到
CPU时间片来执行垃圾收集任务;
Reference Handler 引用处理器,这是所有线程里面优先级最高的线程,为10。处理引用是Java虚拟机
优先执行的任务;
Signal Dispatcher 信号分发器,优先级是5;
AWT-Windows 优先级5;
AWT-EventQueue-0 优先级6;
SunToolkit.PostEventQueue-0 优先级6;
Screen Updater 优先级4

优先级的设置原则,严重耗费CPU资源的线程,优先级应当设置的低一些。
只有生命周期短,运算量少的线程,可以将优先级设置的高一些。

在Java2以后,如果包含GUI组件,那么虚拟机启动的时候就会包含这8个线程。

线程的六种状态,这六种状态不是Java标注,但是可以有效的帮助我们理解Java线程
1 running
2 ready-to-run
3 sleeping
4 waiting
5 blocked on IO
6 blocked on sync key word

阻塞线程的一些方法
1 线程的睡眠,调用Thread.sleep()方法(解除睡眠状态可以使用interrupt方法或者自然睡醒)
2 线程中的代码,遇到wait()表达式(解除等待状态,一直到等到notify()方法调用,或者被interrupt,或者等待一个超时的时间)

记住,当一个线程被IO流和synchronized关键字阻塞的时候,是不能被interrupt的

自愿放弃处理器资源的方法static Thread.yield()
这个方法,当前线程自动放弃处理器资源,让位于其他线程,可能的情况是优先级大约等于这个线程的
线程先被执行。当当前线程调用sleep()方法的时候,实际上是隐式的调用了yield();在某个线程
被阻塞的