title: 线程基本操纵
date: 2019-04-18 23:31:11
tags:Thread
线程基本操纵
示例代码如下:
public class RunnableDemo implements Runnable {
public Thread t;
private String threadName;
boolean suspended = false;
RunnableDemo(String name) {
threadName = name;
System.out.println("creating " + threadName);
}
@Override
public void run() {
System.out.println("running " + threadName);
try {
for (int i = 10; i > 0; i--) {
System.out.println("thread: " + threadName + ", " + i);
// let the thread sleep for a while
Thread.sleep(300);
synchronized (this) {
while (suspended) {
wait();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("thread " + threadName + " interrupted");
}
}
public void start() {
System.out.println("starting " + threadName);
if (t == null) {
t = new Thread(this, threadName);
t.start();
}
}
void suspend() {
suspended = true;
}
synchronized void resume() {
suspended = false;
notify();
}
}
public class TestThread {
public static void main(String[] args) throws InterruptedException {
RunnableDemo r1 = new RunnableDemo("Thread-1");
r1.start();
RunnableDemo r2 = new RunnableDemo("Thread-2");
r2.start();
try {
Thread.sleep(1000);
r1.suspend();
System.out.println("suspending first thread");
Thread.sleep(1000);
r1.resume();
System.out.println("resuming first thread");
r2.suspend();
System.out.println("suspending second thread");
Thread.sleep(1000);
r2.resume();
System.out.println("resuming second thread");
} catch (InterruptedException e) {
System.out.println("main class interrupted");
}
try {
System.out.println("waiting for threads to finish.");
r1.t.join();
r2.t.join();
} catch (InterruptedException e) {
System.out.println("main thread interrupted");
}
System.out.println("main class exiting.");
}
}
输出如下(每一次的输出结果不一定,下边会分析):
creating Thread-1
starting Thread-1
running Thread-1
thread: Thread-1, 10
creating Thread-2
starting Thread-2
running Thread-2
thread: Thread-2, 10
thread: Thread-1, 9
thread: Thread-2, 9
thread: Thread-1, 8
thread: Thread-2, 8
thread: Thread-2, 7
thread: Thread-1, 7
suspending first thread
thread: Thread-2, 6
thread: Thread-2, 5
thread: Thread-2, 4
resuming first thread
thread: Thread-1, 6
suspending second thread
thread: Thread-1, 5
thread: Thread-1, 4
thread: Thread-1, 3
resuming second thread
waiting for threads to finish.
thread: Thread-2, 3
thread: Thread-1, 2
thread: Thread-2, 2
thread: Thread-1, 1
thread: Thread-2, 1
main class exiting.
下面我们来分析下:
第一步:
RunnableDemo r1 = new RunnableDemo("Thread-1");
这一步在main线程里执行,会实例化一个RunnableDemo对象,根据Runnable的定义,会执行这一句
System.out.println("creating " + threadName);
// 也即打印creating Thread-1
然后执行下面这一句:
r1.start();
这里是调用r1对象的一个普通方法,会执行里边定义的打印数据:
System.out.println("starting " + threadName);
// 也即打印starting Thread-1
在r1执行完打印后,程序会去执行r1里的线程的start方法,此时需要考虑下,程序会怎么执行?大家可以先思考下。
经测试,程序有可能会先打印running Thread-1,有可能会先执行creating Thread-2,因为有可能在子线程的run方法
被调用的时候,子线程没有立马获取到CPU的执行权限,也有可能获取到了,所以会出现这一不同的情况。
在main线程执行完
RunnableDemo r2 = new RunnableDemo("Thread-2);
r2.start();
的时候,此时系统有三个线程,Thread-1, Thread-2,Main-Thread,三个线程交替获取CPU的时间分片。
在Thread-1第一次打印Thread:Thread-1,10的时候,r1线程阻塞300ms,Thread-2同理(后边每打印一次都是阻塞300ms)。
在某一时刻,Main-Thread获得CPU,执行Thread.sleep(1000);主线程阻塞1000ms,此时Thread-1和Thread-2交替
获得CPU的时间分片,待1000ms过后,此时又是Thread-1、Thread-2、Main-Thread三个线程抢占CPU时间片;在某一时刻,Main-Thread
获取到CPU,执行r1.suspend()方法,将r1的挂起状态设置为true;待Thread-1阻塞300ms时间过去后,Thread-1又变成runnable的状态,
可以去争抢CPU资源,当争抢到CPU资源到时候,接着上次断点的地方继续执行,即下边的逻辑:
synchronized (this) {
while (suspended) {
wait();
}
}
Thread-1判断suspended为true,则执行wait()方法,释放锁资源,将自己挂起,等待通知执行;待Main-Thread执行的
Thread.sleep(1000)过完1000ms后,Main-Thread又变成Runnable状态,重新去争抢CPU资源,待争抢到后,
执行r1.resume()方法,重新唤醒Thread-1;r2同理。
在Main-Thread里执行下边两句:
r1.t.join();
r2.t.join();
意思是要等到Thread-1和Thread-2都执行完毕,Main-Thread后续才开始执行,所以我们会看到,这一句永远是在最后执行的:
System.out.println("main class exiting.");
思考以下,如何保证main class existing可以不用在最后打印?以及如何保证,开始的几行,一定按照如下顺序打印:
creating Thread-1
starting Thread-1
running Thread-1
thread:Thread-1,10
creating Thread-2
starting Thread-2
running Thread-2
thread: Thread-2,10
网友评论