第一个并发程序:定义任务和驱动任务

  并发编程使我们可以将程序划分为多个分离的,独立运行的任务通过使用多线程机制,这些独立任务(也被成为子任务)中的每一个都将由执行线程来驱动。在使用线程时,CPU将轮流给每个任务分配其占用时间。每个任务都觉得自己在一直占用CPU,但事实上CPU时间是划分成片段分配给了所有的任务。

定义任务

线程可以驱动任务,因此我们需要一种描述任务的方式,实现Runnable接口并编写run()方法即可定义任务。例如下面的显示代码:

package com;

/**
 * 类LiftOff.java的实现描述:显示发射之前的倒计时
 * 
 * @author wql 2016年9月21日 下午1:46:46
 */
public class LiftOff implements Runnable {

    public LiftOff(){
        taskCount++;//计数自增
    }

    private int        countDown = 3;        // 倒计时数字

    private static int taskCount = 0;   

    private int        id        = taskCount;

    @Override
    public void run() {

        while (countDown >= 0) {
            System.out.println("线程编号" + id + "--倒计时" + countDown);
            countDown--;
            Thread.yield();
} } }
//Thread.yield()的调用是对线程调度器的一种建议,声明自身已完成重要的部分,可将程序切换给其他任务执行。

此时可以直接用main方法调用run(),但这种方式并不会产生任何线程能力,就像你调用一个普通的类方法一样。
package com;

public class Main {

    public static void main(String[] args) {
        LiftOff liftOff = new LiftOff();
        liftOff.run();
        System.out.println("end");
    }

}

输出:

线程编号0--倒计时3
线程编号0--倒计时2
线程编号0--倒计时1
线程编号0--倒计时0
end

驱动任务

将Runnable对象转变为工作任务的方式是把它提交给一个Thread构造器:

package com;

public class Main {

    public static void main(String[] args) {
        Thread t = new Thread(new LiftOff());
        t.start();
        System.out.println("end");
    }

}

输出:

end
线程编号0--倒计时3
线程编号0--倒计时2
线程编号0--倒计时1
线程编号0--倒计时0

通过调用Thread的start()方法启动任务,此时LiftOff.run()由一个新的线程执行,程序的main()方法也是一个线程,因此,程序会“同时”运行两个方法,我们看到“end”先被输出。

我们可以很容易添加更多的线程去驱动更多的任务:

package com;

public class Main {

    public static void main(String[] args) {
        for (int i = 0; i < 3; i++) {
            new Thread(new LiftOff()).start();
        }
        System.out.println("end");
    }

}

输出:

线程编号0--倒计时3
线程编号2--倒计时3
end
线程编号1--倒计时3
线程编号2--倒计时2
线程编号2--倒计时1
线程编号2--倒计时0
线程编号0--倒计时2
线程编号0--倒计时1
线程编号0--倒计时0
线程编号1--倒计时2
线程编号1--倒计时1
线程编号1--倒计时0

输出说明不同任务的执行在线程被切换时混在了一起,而每一次的输出结果可能会完全不同,因为线程调度机制是非确定性的。

 


原文地址:https://www.cnblogs.com/qilong853/p/5892544.html