美文网首页
Java 多线程基本操作

Java 多线程基本操作

作者: Choleece | 来源:发表于2019-04-18 23:37 被阅读0次

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

相关文章

网友评论

      本文标题:Java 多线程基本操作

      本文链接:https://www.haomeiwen.com/subject/tqffgqtx.html