【Java基础】线程笔记——ThreadApi
来源:互联网 发布:防蓝光 软件 编辑:程序博客网 时间:2024/04/30 14:38
线程的中断机制
第一种方法: Thread.stop() (已废弃)
【缺点】线程不安全,已不再使用
第二种方法: Thread.interrupt()
当一个线程运行时,另一个线程可以调用对应的 Thread 对象的 interrupt()方法来中断它,该方法只是在目标线程中设置一个标志,表示它已经被中断,并立即返回。
如果只是单纯的调用 interrupt()方法,线程并没有实际被中断,会继续往下执行
public class InteruptThread implements Runnable { @Override public void run() { boolean stop = false; while(!stop){ System.out.println("This Thread is Running ......"); long time = System.currentTimeMillis(); while((System.currentTimeMillis() - time < 1000)){ } //当interrupt=true时,需要去处理它的中断状态,不然线程会一直运行 if(Thread.currentThread().isInterrupted()){ Thread.currentThread().interrupt(); break; } } System.out.println("This Thread Exit Under Request"); } }
运行
public static void main(String[] args) throws InterruptedException { Thread t = new Thread(new InteruptThread(),"Interupt"); System.out.println("InteruptThread starting ..."); t.start(); Thread.sleep(3000); System.out.println("InteruptThread interupted"); t.interrupt(); System.out.println("线程是否中断---->"+t.isInterrupted()); Thread.sleep(3000); System.out.println("Stop Application");}
console
InteruptThread starting ...This Thread is Running ......This Thread is Running ......This Thread is Running ......InteruptThread interupted线程是否中断---->trueThis Thread Exit Under RequestStop Application
如果去掉if语句判断去处理中断状态,线程一直会一直运行(形成死循环)
InteruptThread starting ...This Thread is Running ......This Thread is Running ......This Thread is Running ......InteruptThread interupted线程是否中断---->trueThis Thread is Running ......This Thread is Running ......This Thread is Running ......Stop ApplicationThis Thread is Running ......This Thread is Running ......
注意:一定要对Thread.isInterrupted()状态进行处理
补充(yield()和join()使用)
- join 方法用线程对象调用,如果在一个线程 A 中调用另一个线程 B 的 join 方法,线程 A 将会等待线程 B 执行完毕后再执行。
- yield 可以直接用 Thread 类调用,yield 让出 CPU 执行权给同等级的线程,如果没有相同级别的线程在等待 CPU 的执行权,则该线程继续执行。
守护线程(后台运行线程)
守护线程不需要关心它何时结束,进程结束,守护线程自动结束
不要在守护线程中执行业务逻辑操作(比如对数据的读写等)
必须在启动线程前标记守护线程
setDeamon(true);
Java垃圾回收、内存管理就是一个守护线程
注意
- setDaemon(true)必须在调用线程的 start()方法之前设置,否则会跑出 IllegalThreadStateException 异常。
- 在守护线程中产生的新线程也是守护线程。
- 不要认为所有的应用都可以分配给守护线程来进行服务,比如读写操作或者计算逻辑
线程阻塞
- 当线程执行 Thread.sleep()时,它一直阻塞到指定的毫秒时间之后,或者阻塞被另一个线程打断;
- 当线程碰到一条 wait()语句时,它会一直阻塞到接到通知(notify())、被中断或经过了指定毫秒时间为止(若制定了超时值的话)
- 线程阻塞与不同 I/O 的方式有多种。常见的一种方式是 InputStream的read()方法,该方法一直阻塞到从流中读取一个字节的数据为止,它可以无限阻塞,因此不能指定超时时间;
- 线程也可以阻塞等待获取某个对象锁的排他性访问权限(即等待获得 synchronized 语句必须的锁时阻塞)。
线程组
方便管理线程,并且可以为某些线程设置相同特定的属性
例如:setDeamon()、设置未处理异常的处理方法、设置统一的安全策略等
每个ThreadGroup都可以包含一组子线程或者一组子线程组
在一个进程中线程组是以树形存在
system线程组是所有线程的顶级父线程组
//获取当前线程的线程组Thread.currentThread().getThreadGroup()
- Java中允许对一个线程组中所有线程进行操作
- Java多线程另一个重要的特性就是线程安全。线程组机制允许通过分组来区分不同特性的线程
线程池和线程组区别:线程组方便管理线程对象。线程池管理线程的声明周期,复用线程,减少创建销毁进程的开销
线程安全
当前线程副本ThreadLocal
- ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每个线程都可以独立的改变自己的副本(Local想表达的意思)
- remove() 是jdk5以后新增的方法,java会自动垃圾回收变量,调用该方法加快垃圾回收的速度
- get()/set() 得到/设置ThreadLocal的值
-initialValue() 返回变量的初始值,只执行一次。若缺省,直接返回一个null
public class ThreadLocalValue { private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){ protected Integer initialValue() {return 0;}; }; public Integer nextNum(){ seqNum.set(seqNum.get() + 1); return seqNum.get(); } public ThreadLocal<Integer> getThreadLocal(){ return seqNum; }}
运行
public static void main(String[] args) { ThreadLocalValue value = new ThreadLocalValue(); TestClient t1 = new TestClient(value); TestClient t2 = new TestClient(value); TestClient t3 = new TestClient(value); t1.start(); t2.start(); t3.start(); } static class TestClient extends Thread{ private ThreadLocalValue tlv = null; public TestClient(ThreadLocalValue tlv){ this.tlv = tlv; } @Override public void run() { for (int i = 0; i < 3; i++) { System.out.println("thread["+Thread.currentThread().getName()+"] ---> value : "+tlv.nextNum()); } tlv.getThreadLocal().remove(); }}
console
thread[Thread-2] ---> value : 1thread[Thread-1] ---> value : 1thread[Thread-0] ---> value : 1thread[Thread-1] ---> value : 2thread[Thread-2] ---> value : 2thread[Thread-1] ---> value : 3thread[Thread-0] ---> value : 2thread[Thread-0] ---> value : 3thread[Thread-2] ---> value : 3
上面可得出
所产生的序号虽然共享一个实例,但是没用互相干扰,而是各自独立产生序列号,确定每个线程单独提供了一个变量副本
源码解析
set
1.首先通过getMap(t)得到当前相关ThreadLocalMap,将值放入map中,如果为空则重新创建Map createMap(t,value)
ThreadLocalMap 是线程隔离的核心,它是ThreadLocal的静态内部类,实现了键值对的设置和获取(对比Map) 存储的值,只能被当前线程读取和修改,ThreadLocal操作每个线程特有的ThreadLocalMap,从而实现了变量在不同线程中的隔离
ThreadLocalMap的键的this对象指的就是ThreadLocal,值就是所存储的值。
static class ThreadLocalMap
总结
ThreadLocal处理线程的局部变量,要比synchronized同步机制解决线程问题更简单,更方便,而且结果程序拥有更高的并发性
线程的异常处理
所有异常必须在run方法进行处理,不能抛出throw exception
- 方法一:在try…catch内处理
- 方法二:实现一个UncaughtExceptionHandler接口
处理unchecked异常
设计一个异常线程B
public class ThreadB implements Runnable { @Override public void run() { int num = Integer.parseInt("A"); System.out.println(num); System.out.println("This is Exception Thread B "); }}
处理线程异常
public class ExceptionOfThreadB implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.println("Thread -->"+t.getName()+"("+t.getId()+")"); System.out.println("Thread Exception -->"+e.getClass().getName()); System.out.println("exception message -->"+e.getMessage()); System.out.println("state -->" + t.getState()); }}
运行
public static void main(String[] args) { ThreadB threadException = new ThreadB(); Thread t = new Thread(threadException,"threadException"); //设置异常 t.setUncaughtExceptionHandler(new ExceptionOfThreadB()); t.start(); }
console
Thread -->threadException(10)Thread Exception -->java.lang.NumberFormatExceptionexception message -->For input string: "A"state -->RUNNABLE
- 【Java基础】线程笔记——ThreadApi
- java线程基础——笔记
- java线程基础——笔记2
- 【Java基础】线程笔记——synchronized
- 【java基础】线程笔记——LockSupport
- 【Java基础】线程笔记——线程安全
- 笔记-java线程基础
- Java基础—线程
- Android学习笔记——java线程基础
- 【JAVA笔记——道】Hibernate 线程本地化基础篇
- 【Java基础】线程笔记——显式锁Lock和ReentrantLock
- 【Java基础】线程笔记——显式锁StampedLock
- 【java基础】线程笔记——AQS(AbstractQueuedSynchronizer)
- 黑马程序员—Java基础学习笔记之多线程
- Java基础笔记之多线程
- [Java基础笔记]线程部分
- 【Java基础】线程笔记——创建线程的3种方式
- java基础—— 线程
- js把时间戳转换为日期格式
- Ubuntu16.04 安装Haroopad
- Leetcode题解
- Python做文本挖掘的情感极性分析
- 平衡数的求解
- 【Java基础】线程笔记——ThreadApi
- 数据驱动---JAVA读取excle数据
- 图像复原之由投影重建图像
- LVS搭建负载均衡的环境
- JVM学习笔记(三)------内存管理和垃圾回收
- 采用dlopen、dlsym、dlclose加载动态链接库【总结】
- FZU1050 Number lengths(数论,规律,概念)
- 欢迎使用CSDN-markdown编辑器
- shell学习