您的位置:首页 > 编程语言 > Java开发

java并发编程之Thread类详细使用(四)

2017-12-12 17:28 330 查看
原博文地址:http://www.cnblogs.com/dolphin0520/p/3920357.html

1.线程的状态:new(创建)->runnable(就绪)->running(运行),运行时又分状态:阻塞(blocked),time waiting(睡眠或等待一定的事件),waiting(等待被唤醒)。

线程执行完毕,或者突然中断,进入dead(死亡or销毁)状态。如下图所示:



2.Thread之sleep()方法:

1)sleep相当于让线程睡眠,交出CPU,让CPU去执行其他的任务。

2)sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则即使调用sleep方法,其他线程也无法访问这个对象。

例子如下:

public class Threadsleep {

private int i = 10;
private Object object = new Object();

public static void main(String[] args) throws IOException {
Threadsleep threadsleep = new Threadsleep();
//下面两个线程共享threadsleep对象
MyThread thread1 = threadsleep.new MyThread();
MyThread thread2 = threadsleep.new MyThread();
thread1.start();
thread2.start();
}

class MyThread extends Thread{
@Override
public void run() {
synchronized (object) {
i++;
System.out.println("i:"+i);
try {
System.out.println("线程"+Thread.currentThread().getName()+"进入睡眠状态");
Thread.currentThread().sleep(10000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println("线程"+Thread.currentThread().getName()+"睡眠结束");
i++;
System.out.println("i:"+i);
}
}
}

}

结果:



结论:当Thread-0进入睡眠状态之后,Thread-1并没有去执行具体的任务。只有当Thread-0执行完之后,此时Thread-0释放了对象锁,Thread-1才开始执行。

3.Thread之join()方法:

join()
join(long millis) //参数为毫秒
join(long millis,int nanoseconds) //第一参数为毫秒,第二个参数为纳秒
1)假如在main线程中,调用thread.join方法,则main方法会等待thread线程执行完毕或者等待一定的时间。

2)如果调用的是无参join方法,则等待thread执行完毕,如果调用的是指定了时间参数的join方法,则等待一定的事件。

例子如下:

public class Threadjoin {

public static void main(String[] args) throws IOException {
System.out.println("进入线程"+Thread.currentThread().getName());
Threadjoin threadjoin = new Threadjoin();
MyThread thread1 = threadjoin.new MyThread();
thread1.start();
try {
System.out.println("线程"+Thread.currentThread().getName()+"等待");
thread1.join();
System.out.println("线程"+Thread.currentThread().getName()+"继续执行");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

class MyThread extends Thread{
@Override
public void run() {
System.out.println("进入线程"+Thread.currentThread().getName());
try {
Thread.currentThread().sleep(5000);
} catch (InterruptedException e) {
// TODO: handle exception
}
System.out.println("线程"+Thread.currentThread().getName()+"执行完毕");
}
}
}结果:



结论:1)当调用thread1.join()方法后,main线程会进入等待。然后等待thread1执行完之后再继续执行。

2)thread1.join()后让main线程进入阻塞状态,并且会释放线程占有的锁,并交出CPU执行权限。

4.Thread之interrupt方法:

1)interrupt,顾名思义,即中断的意思。

2)单独调用interrupt方法可以使得处于阻塞状态的线程抛出一个异常,也就说,它可以用来中断一个正处于阻塞状态的线程。

例子如下:

public class Threadinterrupt {

public static void main(String[] args) throws IOException {
Threadinterrupt threadinterrupt = new Threadinterrupt();
MyThread thread = threadinterrupt.new MyThread();
thread.start();
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {

}
thread.interrupt();
}

class MyThread extends Thread{
@Override
public void run() {
try {
System.out.println("进入睡眠状态");
Thread.currentThread().sleep(10000);
System.out.println("睡眠完毕");
} catch (InterruptedException e) {
System.out.println("得到中断异常");
}
System.out.println("run方法执行完毕");
}
}

}结果:



结论:1)interrupt方法可以中断处于阻塞状态的线程。

问题:interrupt能不能中断处于非阻塞状态的线程呢?如下例子:

public class Threadinterrupt2 {

public static void main(String[] args) throws IOException {
Threadinterrupt2 threadinterrupt2 = new Threadinterrupt2();
MyThread thread = threadinterrupt2.new MyThread();
thread.start();
try {
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) {

}
thread.interrupt();
}

class MyThread extends Thread{
@Override
public void run() {
int i = 0;
while(i<Integer.MAX_VALUE){
System.out.println(i+" while循环");
i++;
}
}
}

}

结论:通过测试结果,发现直接调用interrupt方法不能中断正在运行中的线程。
问题:如何中断正在运行的线程呢?

1)一般会在MyThread类中增加一个属性 isStop来标志是否结束while循环,然后再在while循环中判断isStop的值。如下:

class MyThread extends Thread{
private volatile boolean isStop = false;
@Override
public void run() {
int i = 0;
while(!isStop){
i++;
}
}

public void setStop(boolean stop){
this.isStop = stop;
}
}

那么就可以在外面通过调用setStop方法来终止while循环。
5.Thread其他方法:

1)getId 用来得到线程ID。

2)getName和setName。用来得到或者设置线程名称。

3)getPriority和setPriority。用来获取和设置线程优先级。

4)setDaemon和isDaemon。用来设置线程是否成为守护线程和判断线程是否是守护线程。

5)currentThread()。常用,用来获取当前线程。

演示关系图如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: