以下内容请参考:大型网站系统与Java中间件实战 72-89页
线程、线程池
synchronized、lock、volatile
Atomics
wait、notify和notifyAll
CountDownLatch
CyclicBarrier
Semaphore
Exchanger
Futuer和FutureTask
并发容器
Thread.yield()的调用是对线程调度器的一种建议(Java线程机制的一部分,可以将CPU从一个线程转移给另一个线程)的一种建议,它在声明:“我已经执行完生命周期中最重要的部分了,此刻正是切换给其它任务执行一段时间的大好时机。”这完全是选择性的。
创建线程的几种机制:
实现Runnable接口:编写一个类实现Runnable接口并编写run()方法(run方法中是定义的要完成的任务代码);然后再另一个类new 该对象并通过对象调用run()方法。
public class LiffOff implements Runnable{
public void run(){
//当前线程要执行的任务
}
}
public class MainThread(){
public static void main(String args[]){
LiffOff launch = new LiffOff();
lauch.run();
}
}
实现Callable接口:Runnable是执行工作的独立任务,但是他不返回任何值。若需要任务完成时能够返回值,则需要实现Callable接口;JDKSE5引入的Callable是一种具有类型参数的泛型,它的类型参数表示的是从方法call()(而不是run())中的返回值,并且必须使用ExecutorService.submit()方法调用它。
public class CallableTest {
public static void main(String[] args) {
ExecutorService exec=Executors.newCachedThreadPool();
List<Future<String>> results=new ArrayList<Future<String>>();
for(int i=0;i<5;i++) {
results.add(exec.submit(new TaskWithResult(i)));
}
for(Future<String> fs :results) {
try {
System.out.println(fs.get());
} catch (InterruptedException|ExecutionException e) {
e.printStackTrace();
}
}
}
}
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;
}
}
使用Thread类:Thread构造器只需要一个Runnable对象。调用Thread对象的start()方法为该线程执行必需的初始化操作,然后调用Runnable的run()方法,以便在这个线程中启动该任务。
public class BasicThread{
public static void main(String[] args){
Thread t= new Thread(new LiftOff());//LiftOff为实现了Runnable接口类
t.start();
}
}
使用Executor:
JDK 1.5 java.util.concurrent包中的执行器(Executor)将为你管理Thread对象,简化并发编程。
ExecutorService exec = Executors.newCachedThreadPool(); CachedThreadPool将为每一个任务都创建一个线程
ExecutorService exec = Executors.newFixedThreadPool(5);FixedThreadPool可限制线程数量,使用有限的线程集执行所提交的任务
ExecutorService exec = Executors.newSignleThreadExecutor();就像线程数为1的FixedThreadPool;提交多个任务时,需要排队,每个任务按照提交的顺序依次执行;SignleThreadExecutor会序列化所有提交给他的任务,并会维护自己的悬挂任务队列。它保证任意时间只有唯一的任务在运行,不需要在共享资源上处理同步
在Java中,我们一般通过集成Thread类和实现Runnnable接口,调用线程的start()方法实现线程的启动。但如果并发的数量很多,而且每个线程都是执行很短的时间便结束了,那样频繁的创建线程和销毁进程会大大的降低系统运行的效率。线程池正是为了解决多线程效率低的问题而产生的,他使得线程可以被复用,就是线程执行结束后不被销毁,而是可以继续执行其他任务
线程池有什么用呢?
一言以蔽之,就是提高系统效率和吞吐量。如果服务器对每个请求都分别创建一个线程的话,在很短时间内就会产生很多创建和销毁的动作,然而服务器在创建和销毁线程上花费的时间和消耗的系统资源都相当大。线程池就可以尽量减少这种情况的发生。
https://blog.youkuaiyun.com/f641385712/article/details/80832636