用实现runnable接口的方法创建线程时要,
00-1010多线程run方法中如何直接调用服务业务类要注意下图:线程启动的四种方式使用@Aysnc注释实现多线程用户线程和守护线程的区别;Java锁的六种状态;睡眠和等待的四种拒绝策略;为什么wait(),notify()和notifyAll()在对象中,而不在线程类中?
目录
Java多线程运行方法使用服务业务类,导致java.lang.NullPointerException异常。这是因为spring注入的业务类是null,或者直接new的业务对象也是null。
多线程为了线程安全会防止注入,所以当你想使用服务业务类的时候,你需要使用ApplicationContext获取bean方法来获取服务类。
获取ApplicationContext的类实现ApplicationContextAware接口,如下所示:
导入org . spring framework . beans . beans exception;导入org . spring framework . context . application context;import org . spring framework . context . applicationcontextaware;公共类ApplicationContextUtil实现ApplicationContextAware { private static application context context;public void setApplicationContext(application context context)抛出beans exception { this . context=context;}公共静态application context get context(){ return context;}}然后使用上述方法在run方法中创建一个业务对象,如下所示:
XXXServiceI xxxService=applicationcontextutil . get context . get bean(XXXServiceI . class);这样商务舱就可以正常使用了。
多线程run方法中直接调用service业务类应注意
图解如下
00-1010 1.继承Thread类,重写Thread的run方法,在run方法中操作,用start方法启动线程。
2.继承runnable接口,实现run方法,在Run方法中操作。需要传入当前类的instance对象来创建一个线程实例,然后调用start方法来启动线程。
3.实现Callable接口并重写call()方法。需要注意的是,前两个方法是直接执行的,没有任何响应。但是实现Callable接口和重写call()方法需要等待线程响应,所以虽然启动了其他线程,但是都是一个线程执行,不是标准的多线程。
4.线程池
00-1010在同一个类中,引用方法B的方法A加上异步@Async注释将无效。
添加的@Async方法和调用方不能在同一个类中。
00-1010 Java中创建的默认线程是创建一个用户线程,比如newthread.start。
Thread thread=新线程();//默认为false,均为用户线程thread . set daemon(true);//表示设置为守护线程. set daemon(false);//表示设置为用户线程no,zhi随着其他线程的死亡而死亡。刀死的情况只有两种。一种是运行过程中因异常而终止,另一种是程序正常执行,线程在用户线程.死亡
trong>:随着用户线程的死亡而死亡,当用户线程死完了守护线程也死了,比如gc垃圾回收线程。用户线程存在,那gc就有活着的必要,反之就没用了。
线程的六种状态
1. New:初始状态,线程被创建,没有调用start()
2. Runnable:运行状态,Java线程把操作系统中的就绪和运行两种状态统一称为运行中
3. Blocked:阻塞,线程进入等待状态,线程因为某种原因,放弃了CPU的使用权
阻塞的几种情况:A. 等待阻塞:运行的线程执行了wait(),JVM会把当前线程放入等待队列B. 同步阻塞:运行的线程在获取对象的同步锁时,如果该同步锁被其他线程占用了,JVM会把当前线程放入锁池中C. 其他阻塞:运行的线程执行sleep(),join()或者发出IO请求时,JVM会把当前线程设置为阻塞状态,当sleep()执行完,join()线程终止,IO处理完毕线程再次恢复4. Waiting:等待状态
5. timed_waiting:超时等待状态,超时以后自动返回
6. terminated:终止状态,当前线程执行完毕
Java锁的可重入性
java锁的可重入性机制可以解决下面这个问题,直接上代码:
public class Demo1 { public synchronized void functionA(){ System.out.println("iAmFunctionA"); functionB(); } public synchronized void functionB(){ System.out.println("iAmFunctionB"); }
假设Java没有提供synchronized 强制原子性的内部锁机制:functionA()和functionB()都是同步方法,当线程进入funcitonA()会获得该类的对象锁,这个锁"new Demo1()",在functionA()对方法functionB()做了调用,但是functionB()也是同步的,因此该线程需要再次获得该对象锁(new Demo1()),但是JVM会认为这个线程已经获取了此对象的锁,而不能再次获取,从而无法调用functionB()方法,从而造成死锁。
线程池的四种拒绝策略
当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize时,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:
ThreadPoolExecutor.AbortPolicy
:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy
:丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy
:丢弃队列最前面的任务,然后重新提交被拒绝的任务
ThreadPoolExecutor.CallerRunsPolicy
:由调用线程(提交任务的线程)处理该任务
sleep和wait的区别
sleep是线程中的方法,但是wait是Object中的方法sleep方法不会释放lock,但是wait会释放,而且会加入到等待队列中sleep不需要被唤醒,但是wait需要
为什么wait(),notify(),notifyAll()在对象中,而不在Thread类中
java中锁的级别是对象级而不是线程级,每个对象都有锁,通过线程获得。如果wait()方法在线程中,线程正在等待的是哪个锁就不明显了。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持盛行IT。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。