并发编程基础小结-线程

2018-01-02  本文已影响11人  r09er

在并发编程中,线程的使用是首要的,没有多线程就不存在所谓的并发了.

创建线程的步骤和方式

new Thread().start() 这种方式不要再使用了,这是最低级的线程创建方法.

1.定义任务

定义任务,一般有三种方式:

i.实现Runnable接口,没有返回值
public 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();
        }
    }
}

Thread.yield(); 的调用是对线程调度器的一种建议,它的意思是:我已经执行完生命周期中最重要的部分了,此刻正是切换给他其他任务执行一段时间的机会. 该方法的调用时可选的,调用了可以更好的观察线程的切换的证据

ii.实现Callable<T> 方法,泛型参数是返回值
public class TaskWithResult implements Callable<String> {

    private int id;

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

    @Override
    public String call() throws Exception {
        return "result of TaskWithResult " + id;
    }
}
iii.继承Thread类,重写run方法,没有返回值
public class SimpleThread extends Thread{

    private int countDown = 5;

    private static int threadCount = 0;

    public SimpleThread() {
        super(Integer.toString(++threadCount));
    }

    @Override
    public String toString() {
        return "#"+getName()+"("+countDown+"),";
    }

    @Override
    public void run() {
        while (true){
            System.out.println(this);
            if (--countDown==0) {
                return;
            }
        }
    }
}

2.使用Executor,调用execute(Runnable run)或者submit(Callable call),

代码中使用的CachedThreadPool会为每一个任务都创建一个线程.

  ExecutorService executor = Executors.newCachedThreadPool();
        for (int i = 0; i < 5; i++) {
            executor.execute(new LiftOff());
        }
        executor.shutdown();

executor.shutdown()会将调用该方法之前提交的任务有序的关闭,并且新提交的任务也不会被接收.

在示例中,main()方法的进程会一直运行,直到Executor中所有的任务完成.完成之后会尽快退出整个程序.

不同的Executors

无论创建何种线程池,在可能的情况下,都会被自动复用.

CachedThreadPool

CachedThreadPool会在程序执行过程中创建与所需数量相同的线程,然后在它回收线程时停止创建新线程,一般是Executor的首选.

FixedThreadPool

FixedThreadPool在创建的时候要求传入一个创建的线程总数,一次性预执行代价高昂的线程分配,可以控制线程的总数量.

SingleThreadExecutor

SingleThreadExecutor是线程数只有1的线程池,如果向SingleThreadExecutor提交了多个任务,任务会排队,每个任务都会在下一个任务开始之前结束,所有的任务都会使用同一个线程.

ScheduledThreadPool

ScheduledThreadPool是可以指定线程数的延迟队列线程池,可以执行周期性和延迟的任务

SingleThreadScheduledExecutor

SingleThreadScheduledExecutor相当于线程数只有1的ScheduledThreadPool.

优化线程池ThreadPoolExecutor

线程池极大改善了系统的性能,不过创建线程池也是需要资源的,所以线程池内线程数量的大小也会影响系统的性能,大了反而浪费资源,小了反而影响系统的吞吐量,所以我们创建线程池需要把握一个度才能合理的发挥它的优点, 通常核心线程数可以设为CPU数量+1,而最大线程数可以设为CPU的数量*2+1。

获取CPU数量的方法为:

Runtime.getRuntime().availableProcessors()
上一篇 下一篇

猜你喜欢

热点阅读