首先要了解什么是thread.uncaughtexceptionhandler,默认来说当线程出现未捕获的异常时,会中断并抛出异常,抛出后的动作只有简单的堆栈输出。如:
public class threadtest{ public static void main(string[] args) throws exception{ thread t1=new thread(new runnable(){ public void run(){ int a=1/0; } }); t1.start(); } }
那么代码运行到int a=1/0;就会报错:
exception in thread "thread-0" java.lang.arithmeticexception: / by zero at yiwangzhibujian.threadtest$1.run(threadtest.java:11) at java.lang.thread.run(thread.java:662)
这时候如果设置了thread.uncaughtexceptionhandler,那么处理器会将异常进行捕获,捕获后就可以对其进行处理:
public class threadtest{ public static void main(string[] args) throws exception{ thread t1=new thread(new runnable(){ public void run(){ int a=1/0; } }); t1.setuncaughtexceptionhandler(new uncaughtexceptionhandler(){ @override public void uncaughtexception(thread t,throwable e){ system.out.println("线程:"+t.getname()+"出现异常,异常信息:"+e); } }); t1.start(); } }
那么当线程抛出异常后就可以对其抓取并进行处理,最终结果如下:
线程:thread-0出现异常,异常信息:java.lang.arithmeticexception: / by zero
如果自己写线程,那么完全可以在run方法内,将所有代码进行try catch,在catch里做相同的操作。uncaughtexceptionhandler的意义在于不对(或者不能对)原有线程进行修改的情况下,为其增加一个错误处理器。
2.interrupt() 、interrupted() 、isinterrupted()作用:
这样就由程序来决定当检测到中断属性为true时,怎么对线程中断进行处理。因此,代码可以改成:
@override public void run(){ while(!thread.currentthread().isinterrupted()){ //执行某些任务 } } --------------------------------------------------------- @override public void run(){ //耗时较长步骤1 if(thread.currentthread().isinterrupted()) return; //耗时较长步骤2 if(thread.currentthread().isinterrupted()) return; //耗时较长步骤3 }
stop方法会立即中断线程,虽然会释放持有的锁,但是线程的运行到哪是未知的,假如在具有上下文语义的位置中断了,那么将会导致信息出现错误,比如:
@override public void run(){ try{ //处理资源并插入数据库 }catch(exception e){ //出现异常回滚 } }
如果在调用stop时,代码运行到捕获异常需要回滚的地方,那么将会因为没有回滚,保存了错误的信息。
而suspend会将当前线程挂起,但是并不会释放所持有的资源,如果恢复线程在调用resume也需要那个资源,那么就会形成死锁。当然可以通过你精湛的编程来避免死锁,但是这个方法具有固有的死锁倾向。所以不建议使用。其他暂停方法为什么可用:
首先应该记住以下基本点,先背下来也无妨:
threadlocal这个对象就是为多线程而生的,没有了多线程threadlocal就没有存在的必要了。可以将任何你想在每个线程独享的对象放置其中,并在任何时候取出来。
使用threadlocal不会导致内存泄漏。
public class threadlocaluse{ //创建一个静态的threadlocal对象,当做仓库,存储每个线程自己的资源 //此处用object来代替,可以使连接connection private static threadlocal<object> store=new threadlocal<object>(); //当每个线程要获取一个线程资源的时候,调用get方法 public object get(){ //首先去仓库中去寻找 object obj=store.get(); //如果不存在那就创建一个给线程,并把创建的放到仓库中 if(obj==null){ obj=new object(); set(obj); } return obj; } //想将线程资源放到仓库调用set方法, public void set(object obj){ store.set(obj); } }
很多人都会对这两个对象进行比对,我也谈一下我自己的想法。
使用synchronized是为了将多条语句进行原子化操作,比说对于递增操作i++,任意一个线程在执行代码时都要保证别的线程不能执行这个代码,否则就会产生脏数据,使用synchronized可以避免这一点。
而使用threadlocal就是给每个线程存储对象用的。既然每个线程使用了自己的对象,没有了竞争就不会出现多线程相关的问题。
多线程怎么防止竞争资源,即防止对同一资源进行并发操作,那就是使用加锁机制。这是java并发编程中必须要理解的一个知识点。其实使用起来还是比较简单,但是一定要理解。
有几个概念一定要牢记:
synchronized : 的特点是自动释放锁,作用在方法时自动获取锁,任意对象都可做为锁,它是最常用的加锁机制,锁定几行代码,如下:
//--------同步方法1 public synchronized void test(){ //一段代码 } //--------同步方法2,锁某个对象 private object lock=new object(); public void test2(){ synchronized(lock){ } }
lock : 的特点是,必须自己创建锁(锁类型已经指定为lock的实现类,不能使用其它对象),必须自己释放锁。代码结构如下:
lock lc = new lock(); lc.lock(); try { // 执行代码 } finally { lc.unlock(); }
//注意一定要在finally中释放锁,保证即便抛出异常也可以释放。
如对本文有疑问, 点击进行留言回复!!
ScrollView和RecyclerView的滑动事件处理
配置JAVA环境+安装Android Studio全过程+踩坑记录
Android P Camera2当SD卡被拔出来自动切换到内部存储
android 多个edittext 判空监听 让Button动态是否可点击
Android开源项目滚轮选择器WheelPicker的基本用法总结
网友评论