1,什么是死锁
2.线程通信(了解wait和sleep的区别)
3.线程都有哪些状态
4,线程池
5.Callable创建线程
1,什么是死锁
Java中的死锁是指两个或多个线程互相持有对方所需要的资源,导致所有线程无法继续执行下去,并且无法释放资源以继续执行。
如当一个线程拥有A对象锁标记,并等待B对象锁标记,同时第二个线程拥有B对象锁标记,并等待A对象标记时,产生死锁。
一个线程可以同时拥有多个对象的锁标记,当线程阻塞时,不会释放已经拥有的锁标记,由此可能照成死锁。
如何解决死锁:
(1)减少同步代码 块的嵌套。
(2)设置锁的超时时间。
(3)可以使用安全类-jdk提高的安全类
2.线程通信(了解wait和sleep的区别)
在Java中,线程通信是指多个线程之间通过共享的对象进行信息交换和同步工作。线程通信可以用于协调不同线程之间的操作,以实现数据的安全共享和顺序执行。
线程通信的机制:
-
wait()和notify():使用Object类的wait()和notify()方法可以实现线程的等待和唤醒操作。通过在某个对象上调用wait()方法,线程将进入等待状态,并释放对象的锁。而其他线程可以调用notify()方法来唤醒等待的线程。(这里只将这一种通信机制,还有其他通信机制可自行 上网查询。)
wait() 方法: 当前线程释放对象锁(监视器)的拥有权,在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,当前线程处于等待状态。
notify() 方法:唤醒在此对象锁(监视器)上等待的单个线程。如果有多个线程都在此对象上等待,则会选择唤醒其中一个线程。选择是任意性的,并且根据实现进行选择。
sleep和wait方法的区别?
(1)来自不同的类:sleep来自于Thread类, wait来自Object类
(2)是否释放锁资源:sleep不会释放锁资源,wait会释放锁资源。
(3)用法:sleep时间到了自然会醒,而wait需要调用notify或notifyAll()方法唤醒。
notify随机唤醒等待队列中的一个线程,而notifyAll会唤醒等待队列中的所有线程
3.线程都有哪些状态
NEW :新建状态 RNNABLE: start()就绪状态-时间片-运行时间,RUNNABLE BLOCKED: 堵塞状态,加锁时是该状态 WAITING: 无期等待,调用wait方法时会进入该状态 TIMED_WAITING: 有期等待,当调用sleep方法时会进入该状态 TERMINATED:终止状态,线程的任务代码执行完毕或者出现异常。
线程的状态之间可以通过调用相应的方法,进行转换。
4.线程池
Java线程池是Java多线程编程中常用的一种技术。它允许程序创建和管理一个线程池,用于执行多个任务,从而提供更高效的线程管理和资源利用。
Java线程池的主要优点包括:
-
线程重用:线程池会重用已经创建好的线程,在任务完成后并不立即销毁线程,而是将其放回线程池中,供下一个任务使用。这样可以避免频繁创建和销毁线程的开销,提高程序的性能。
-
控制并发数量:线程池可以控制同时运行的线程数量,避免系统资源过度占用而导致性能下降或崩溃。可以通过设置线程池的大小来限制并发线程数量。
-
任务排队:当线程池中的线程都在工作时,新提交的任务会被排队等待执行,而不是立即开启新的线程。这种排队机制可以平衡系统资源的利用,防止任务堆积和线程过多。
Executor:它是线程池的根接口 -- void execute (Runnable command):执行Runnable类型的任务 ExecutorService: 它是Executor的子接口。-- void shutdown() : 关闭线程池。需要等任务执行完毕 shutdownNow ():立即关闭线程池,不在接收新的任务 isShutdown ():判断是否执行了关闭 isTerminated() :判断线程池是否终止,表示线程池中的任务都执行完毕了。并且线程池关闭了 submit(Callable<T> task):提交任务,可以提交Callable submit(Runnable task): 提交任务, 可以提交Runnable任务
public class Test03 { //Executors: 它是线程池的工具类,该类提供了创建线程池的一些静态方法 public static void main(String[] args) { // 1.创建一个固定长度的线程池 // ExecutorService executorService = Executors.newFixedThreadPool(5); //2.单一线程池 // ExecutorService executorService1 = Executors.newSingleThreadExecutor(); //3。可变线程池 --缓存线程池 // ExecutorService executorService2 = Executors.newCachedThreadPool(); //4.延迟线程池 ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5); // for(int i=0;i<22;i++){ // executorService2.submit(new Runnable() { // @Override // public void run() { // System.out.println(Thread.currentThread().getName()+"++++++++++++++"); // } // }); // } // for(int i=0;i<22;i++){ // //延迟加载的提交任务方式 // scheduledExecutorService.schedule(new Runnable() { // @Override // public void run() { // System.out.println(Thread.currentThread().getName()+"++++++++++++++"); // } // },6, TimeUnit.SECONDS); // } //上面通过Executors工具类来创建线程池,但是阿里巴巴不建议使用,阿里巴巴建议使用原生的模式创建线程池 /** * int corePoolSize, 核心线程的个数 * int maximumPoolSize, 最大的线程个数 * long keepAliveTime, 线程的空闲时间 * TimeUnit unit, 空闲的单位 * BlockingQueue<Runnable> WorkQueue: 等待队列 */ ArrayBlockingQueue<Runnable> runnables = new ArrayBlockingQueue<>(5);//最多等待5个队列 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, runnables); for(int i=0;i<22;i++){ threadPoolExecutor.submit(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()+"============"); } }); } } }
5.Callable创建线程
public class Test04 { public static void main(String[] args) throws ExecutionException, InterruptedException { MyCallable myCallable = new MyCallable(); //1 // FutureTask<Integer> integerFutureTask = new FutureTask<>(myCallable); // Thread thread = new Thread(integerFutureTask); // thread.start(); // System.out.println(integerFutureTask.get()); //2线程执行步骤太多,用线程池来执行任务, ---不用自己创建对象,而使用线程池中的对象 ExecutorService executorService = Executors.newSingleThreadExecutor(); Future<Integer> submit = executorService.submit(myCallable); System.out.println(submit.get()); } } class MyCallable implements Callable<Integer>{ @Override public Integer call() throws Exception { int result=0; for(int i=0;i<10;i++){ result=result+i; } return result; } }
完、