1.两个线程交替输出1a2b3c4d......z
//解法一:LockSupport.park,unpart
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
t1 = new Thread(()->{
for(char c : aI){
System.out.print(c);
LockSupport.unpark(t2); //叫醒t2
LockSupport.park(); //T1阻塞
}
}, name:"t1");
t2 = new Thread(()->{
for(char c : aC){
LockSupport.park(); //t2阻塞
System.out.print(c);
LockSupport.unpark(t1); //叫醒t1
}
}, name:"t2");
//解法二:wait notify
char[] aI = "1234567".toCharArray();
char[] aC = "ABCDEFG".toCharArray();
new Thread(()->{
synchhroninzed(o){ //wait,notify必须使用sync
for(char c : aI){
System.out.print(C);
try{
o.notify();
o.wait(); //让出锁
}catch(Exception e){
e.printStackTrace();
}
}
o.notify();//必须,否则无法停止程序
}
}, name:"t1").start();
new Thread(()->{
synchhroninzed(o){
for(char c : aC){
System.out.print(C);
try{
o.notify();
o.wait();
}catch(Exception e){
e.printStackTrace();
}
}
o.notify();
}
}, name:"t2").start();
2.线程池
Executor 线程池,有execute方法
ExecutorService实现了Executor接口,并进行拓展。实现了线程生命周期的内容。
ExecutorService有execute和submit方法,区别是execute方法马上执行,submit方法把任务扔给线程池,不管什么时候执行,线程池自己决定。submit异步提交任务,原线程正常执行。
3.Callable接口
Callable类似与Runnable,可以用线程来运行,不同的是Callable有返回值。
V call() throws Exception; //相当于Runnable 中的void run()方法
/**
* ExecutorService
*/
public static void main(String[] args)throws InterruptedException,ExecutionException{
// NO.1
FutureTask<Integer> task = new FutureTask<>(()->{
TimeUnit.MILLISECONDS.sleep(500);
return 1000;
}); //new Callable(){Integer call();}
new Thread(task).start();
System.out.println(task.get());
//NO.2
ExecutorService service = Executors.newFixedThreadPool(5);
Future<Integer> f = service.submit(()->{
TimeUnit.MILLISECONDS.sleep(500);
return 1;
});
System.out.println(f.get());
System.out.println(f.isDone());
}
/*
* Callable
*/
public static void main(String[] args) throws ExecutionException, InterruptedException{
Callable<String> c = new Callable(){
@Override
public String call() throws Exception{
return "hello callable";
}
};
ExecutorService service = Executors.newCachedThreadPool();
Future<String> future = service.submit(c); //异步 future存储执行结果
System.out.println(future.get()); //阻塞
service.shutdown();
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
/**
* FutureTask 即使future又是task,可以作为任务执行,执行结果放在FutureTask里面
* FutureTask实现了RunnableFuture, RunnableFuture实现了Runnable,Future<V>
*/
FutureTask<Integer> task = new FutureTask<>(()->{
TimeUnit.MILLISECONDS.sleep(500);
return 1000;
}); //new Callable(){Integer call();}
new Thread(task).start();
System.out.println(task.get());//阻塞
}
Callable 类似Runnable,但有返回值
Future 存储执行的将来才会产生的结果
FutureTask Future + Runnable
4.ThreadPoolExecutor
ThreadPoolExecutor是ExecutorService的子类;
ExecutorService是Executor的子类;
线程池(线程们(指向线程队列)+ 任务们(指向任务队列))
参数:
corePoolSize:核心线程数,可以设置是否参与归还给操作系统
maxiumPoolSize:最大线程数
keepAliveTime:生存时间,超时将线程归还给操作系统
TimeUnit.SECONDS:生产时间的单位
new ArrayBlockingQueue<Runnable>(capacity:4): 任务队列
Executors.defaultThreadFactory():线程工厂
new ThreadPoolExecutor.DiscardOldestPolicy():拒绝策略
线程池忙,而且任务队列满,执行拒绝策略
拒绝策略:
Abort:抛异常
Discard:扔掉,不抛异常
DicardOldest:扔掉排队时间最久的
CallerRuns:调用者处理任务,谁调用的谁去执行该任务
自定义线程池:7个参数(编码规范推荐)
public static void main(String[] args) {
ThreadPoolExecutor tpe = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(4), //阻塞队列
Executors.defaultThreadFactory(), //线程工厂
new ThreadPoolExecutor.DiscardOldestPolicy());//拒绝策略
for (int i = 0; i< 8; i++){
tpe.execute(new Task(i));
}
System.out.println(tpe.getQueue());
tpe.execute(new Task(100));
System.out.println(tpe.getQueue());
tpe.shutdown();
}
DefaultThreadFactory里面默认设置了:
线程的名字:namePrefix + threadNumber.getAndIncrement() //方便出错回溯
namePrefix = "pool"+poolNumber.getAndIncrement()+"-thread-";
非守护线程:t.setDaemon(false)
线程优先级:t.setPriority(Thread.NORM_PRIORITY)
==================================================================
以上来自马士兵视频:高并发编程。个人学习笔记