在并发编程中,线程的使用是首要的,没有多线程就不存在所谓的并发了.
创建线程的步骤和方式
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()
网友评论