线程通讯:
在多线程中,某个线程进入“等待状态”时,需要某个线程来唤醒
等待方法:
wait()//无线等待wait(long 毫秒)//计时等待
注意,调用wait方法,会自动释放掉锁资源
处于wait状态只能由其他线程唤醒
唤醒方法:
notify();//唤醒处于“等待状态”的任意一个线程,和notify使用相同锁对象的线程notifyAll();//唤醒处于“等待状态”的所有线程
注意,调用notify(),notifyAll()方法,不会自动释放掉锁资源
使用细节:
等待和唤醒的方法,都要使用锁对象调用(需要在同步代码块中使用)
等待和唤醒方法都应该使用相同的锁对象调用
消费者,生产者模型:
//共享资源
public class Resource {static public int number=0;
}
public class test2 {public static void main(String[] args) {Object lock=new Object();//创建消费者线程new Thread(new Runnable() {@Overridepublic void run() {while (true) {synchronized (lock) {if (Resource.number >= 3) {System.out.println("这有足够多的食物");try {lock.wait();//阻塞并释放锁} catch (InterruptedException e) {throw new RuntimeException(e);}} else {Resource.number++;//,一开时number=0,先++再打印System.out.println("[p]:" + Resource.number);lock.notify();//唤醒处于等待状态的线程,且不会释放锁try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}}}).start();Runnable task=new Runnable() {@Overridepublic void run() {while (true) {synchronized (lock) {if(Resource.number==0){System.out.println("这没有足够的资源");try {lock.wait();//阻塞的同时会释放掉锁} catch (InterruptedException e) {throw new RuntimeException(e);}}else {System.out.println("[c]"+Resource.number);//先打印,再--Resource.number--;lock.notify();//唤醒生产者线程,生产者如果没有处于等待,就没事//只能唤醒别的线程try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}}};new Thread(task).start();}}
线程池:
如何获得线程池对象:
方式一:使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象
计算密集型任务:核心线程数:cpu数+1
IO密集型任务:核心线程数:cpu数*2
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
参数一: corePoolSize:指定线程池的核心线程的数量
参数二:maximumPoolSize:指定线程池的最大线程数量
参数三: long keepAliveTime:指定临时线程的存活时间(没有事情干)
参数四:unit:指定临时线程的存活时间单位(分,秒,天)
参数五:workQueue:指定线程池的任务队列
参数六:threadFactory:指定线程池的线程工厂
参数七: handler:指定线程池的任务拒接策略
例如:
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 8, TimeUnit.MINUTES,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),// // Executors.defaultThreadFactory()获取默认的线程池工厂new ThreadPoolExecutor.AbortPolicy());
临时线程什么时候创建:
新任务提交时发现核心线程都在忙,任务对列也满了,并且还可以创建临时线程
什么时候拒绝新任务:
核心线程和临时线程都满了,任务队列也满了
一个任务类:
public class Task1 implements Runnable{@Overridepublic void run() {System.out.println(Thread.currentThread().getName()+"输出yyyy");try{Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}}
}
public class test {public static void main(String[] args) {//创建一个线程池对象ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(3, 5, 8, TimeUnit.MINUTES,new ArrayBlockingQueue<>(4), Executors.defaultThreadFactory(),// // Executors.defaultThreadFactory()获取默认的线程池工厂new ThreadPoolExecutor.AbortPolicy());//添加任务threadPoolExecutor.execute(new Task1());//线程池会自动创建一个线程,自动处理任务threadPoolExecutor.shutdown();//等待线程池所有任务执行完后关闭线程池threadPoolExecutor.shutdownNow();//立即关闭线程池}
}
方式二:使用Executors工具类
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定线程数量的线程池,如果某个线程因为异常关闭,那么线程池会创建出一个新的线程
public static ExecutorService newSingleThreadExecutor()
创建只有一个线程的线程池, 如果这个线程因为异常关闭,那么线程池会创建出一个新的线程
Callable任务:
Interface Callable<V>
Callable支持结果返回,Runnable不行
Callable可以抛出异常,Runnable不行
Callable任务处理使用步骤:
1:创建线程池
2:定义Callable任务
3:创建Callable任务,提交任务给线程池
4:获取执行结果
public class test2 {public static void main(String[] args) throws ExecutionException, InterruptedException {//创建线程池对象ExecutorService executorService = Executors.newFixedThreadPool(10);//创建一个Callable类型的任务类Callable<Integer>callable=new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum=0;for(int i=0;i<10;i++){sum+=i;}return sum;}};//交给线程池处理(submit()方法),并获取返回值Future<Integer> submit = executorService.submit(callable);System.out.println(submit.get());//通过get方法获取返回值}}