线程

21.2.1定义任务

class LiftOff implements Runnable{
    protected int countDown=10;
    private static int taskCount = 0;     
    private final int id = taskCount++;  
    public LiftOff(){}

    public LiftOff(int countDown){
        this.countDown= countDown;
    }

    public String status(){
        return "#" +id +"("+(countDown>0 ? countDown: "Liftoff")+")";
    }

    @Override
    public void run() {
        while (countDown-- >0){
            System.out.println(status());
            Thread.yield(); //本线程暂停,执行其他线程
        }
    }
}

id 用来区分不同的任务对象,用final修饰,所以 taskCount应该定义为 类属性

下面demo中使用main线程调用run()方法

public class Main5_5 {
    public static void main(String[] args){
        new LiftOff().run();
    }
}
output:
#0(9) #0(8) #0(7) #0(6) #0(5) #0(4) #0(3) #0(2) #0(1) #0(Liftoff) 

21.2.2 Thread类

使用Thread类,将Runnable对象传递给Thread构造器,然后调用Thread对象的Start()方法,开启线程

public class Main5_5 {
    public static void main(String[] args){
        for(int i=0;i<5;i++){
            new Thread(new LiftOff()).start();
        }
        System.out.println("wait");
    }
}
output:
wait
#0(9) #1(9) #2(9) #3(9) #4(9) #0(8) #1(8) #2(8) #3(8) #4(8) #0(7) #1(7)
#2(7) #3(7) #4(7) #0(6) #1(6) #2(6) #3(6) #4(6) #0(5) #1(5) #2(5) #3(5)
#4(5) #0(4) #2(4) #3(4) #1(4) #4(4) #0(3) #1(3) #2(3) #3(3) #4(3) #2(2)
#1(2) #0(2) #2(1) #4(2) #3(2) #4(1) #3(1) #2(Liftoff) #3(Liftoff) #1(1)
#0(1) #4(Liftoff) #1(Liftoff) #0(Liftoff) 

demo中使用单一线程main创建所有Liftoff线程,如果多个线程创建 Liftoff线程,id可能会重复

使用Excutor

java.util.concurrent.Executors中的执行器Executor会为你管理Thread对象,从而简化并发编程,

CachedThreadPool创建线程池

public class Main5_5 {
    public static void main(String[] args){
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            exec.execute(new LiftOff());
        }
        exec.shutdown(); //关闭线程执行器,
    }
}
output:
#0(9) #2(9) #1(9) #3(9) #2(8) #0(8) #1(8) #3(8) #2(7) #0(7) #3(7) #4(9)
#0(6) #3(6) #0(5) #2(6) #1(7) #2(5) #0(4) #3(5) #4(8) #3(4) #0(3) #2(4)
#1(6) #2(3) #0(2) #3(3) #4(7) #1(5) #2(2) #3(2) #0(1) #4(6) #1(4) #3(1)
#0(Liftoff) #3(Liftoff) #4(5) #2(1) #1(3) #4(4) #2(Liftoff) #4(3) #1(2)
#1(1) #4(2) #1(Liftoff) #4(1) #4(Liftoff) 

FixedThreadPool,可以指定线程的数量

public class Main5_5 {
    public static void main(String[] args){
        ExecutorService exec = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 5; i++) {
            exec.execute(new LiftOff());
        }
        exec.shutdown();
    }
}

SingleThreadExector,向该线程池提交多个任务,这些任务会排队,按提交的顺序执行依次执行每个任务,当前任务执行完毕之后才会去执行下个任务

public class Main5_5 {
    public static void main(String[] args){
        ExecutorService exec = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 5; i++) {
            exec.execute(new LiftOff());
        }
        exec.shutdown();
    }
}
output:
#0(9) #0(8) #0(7) #0(6) #0(5) #0(4) #0(3) #0(2) #0(1) #0(Liftoff) #1(9)
#1(8) #1(7) #1(6) #1(5) #1(4) #1(3) #1(2) #1(1) #1(Liftoff) #2(9) #2(8)
#2(7) #2(6) #2(5) #2(4) #2(3) #2(2) #2(1) #2(Liftoff) #3(9) #3(8) #3(7)
#3(6) #3(5) #3(4) #3(3) #3(2) #3(1) #3(Liftoff) #4(9) #4(8) #4(7) #4(6)
#4(5) #4(4) #4(3) #4(2) #4(1) #4(Liftoff) 

Callable

Runnable接口中的run()方法只会执行任务,不会返回结果,而Callable接口中的call()方法可以返回,执行任务后的返回值,必须用exec.submit()调用它

Callable<V>接口中的泛型是call()方法的返回值,

public class _Callable {
    public static void main(String[] args){
        ExecutorService exec = Executors.newCachedThreadPool();

        ArrayList<Future<String>> results = new ArrayList<Future<String>>();

        for(int i= 0 ;i<10;i++){
            results.add(exec.submit(new Task(i)));
        }

        for (Future<String> future: results){
            try {
                System.out.println(future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }finally {
                exec.shutdown();
            }
        }
    }

}

class Task implements Callable<String>{
    private int id;

    public Task(int id){
        this.id = id;
    }

    @Override
    public String call() throws Exception {
        return "task id = "+ id;
    }
}
Output:
task id = 0
task id = 1
task id = 2
task id = 3
task id = 4
task id = 5
task id = 6
task id = 7
task id = 8
task id = 9

Future

boolean cancel (boolean mayInterruptIfRunning)
取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束

boolean isCancelled () 判断任务是否已经取消
boolean isDone () 任务是否完成
V get () 获取任务执行结果
V get (long timeout, TimeUnit unit) 获取任务执行结果,可以添加超时时间

21.2.5 Sleep : 当前线程暂停指定时间,系统自己去执行其他线程

public class _4SleepTask extends _1LiftOff {
    public void run() {
        while (countDown-- >0){
            System.out.print(status());
            try {
                // old style :
                //Thread.sleep(5000);
                TimeUnit.MILLISECONDS.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        ExecutorService exec = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            exec.execute(new _4SleepTask());
        }
        exec.shutdown();
    }
}
Output:
#1(9) #0(9) #2(9) #3(9) #4(9) #3(8) #4(8) #0(8) #2(8) #1(8) #3(7) #1(7)
#2(7) #0(7) #4(7) #1(6) #4(6) #0(6) #2(6) #3(6) #1(5) #3(5) #4(5) #2(5)
#0(5) #1(4) #0(4) #3(4) #4(4) #2(4) #1(3) #2(3) #4(3) #0(3) #3(3) #4(2)
#1(2) #3(2) #0(2) #2(2) #1(1) #3(1) #0(1) #2(1) #4(1) #1(Liftoff)
#2(Liftoff) #0(Liftoff) #3(Liftoff) #4(Liftoff) 

21.2.6 线程的优先级setPriority

java中有10个优先级

被volatile修饰的变量能够保证每个线程能够获取该变量的最新值,从而避免出现数据脏读的现象。

public class _2_6Simplepriorities implements Runnable{
    private int shutDown = 5;
    private volatile double d;  
    private int priority;

    public _2_6Simplepriorities(int priority){
        this.priority = priority;
    }

    public String toString(){
        return Thread.currentThread()+" : "+shutDown;
    }


    @Override
    public void run() {
        Thread.currentThread().setPriority(priority);
        while (true){
            for (int i = 0; i < 10000; i++) {
                d += (Math.PI + Math.E)/(double)i;
                if (i%1000==0){
                    Thread.yield();
                }
            }

            System.out.println(this);
            if (--shutDown == 0) return;
        }
    }

    public static void main(String[] args) {
        ExecutorService exec= Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            exec.execute(new _2_6Simplepriorities(Thread.MIN_PRIORITY));
        }
        exec.execute(new _2_6Simplepriorities(Thread.MAX_PRIORITY));
        exec.shutdown();
    }
}

Output:优先级别最高的线程最先执行完任务

21.2.7