一、基础
1、cup核心数据与线程数 早期是1:1关系
但后internet优化,提一核可以同时处理2个线程,所以现在核心数据与线程 1:2
2、cpu时间片轮询机制,cpu在执行任务的时候是把cpu分成一段段时间片,因为时间片太短我们感知不到
3、并发和并行:
并行:同一时刻处理事情的能力
如比:食堂有8个打饭窗口,那么可以同时处理8个人打饭
并发:时间段内处理事情的能力
如比:一个人打饭需1分钟,那么食堂10分钟内的并发能力就是:8x1x10 = 80个, 10分钟内可处理80个人打饭。
4、并发编程好处意义:提升cup利用效,模块化方法
5、注意事项:注意线程安全,容易死锁,线程太多 机器宕机
二、并发编程
有几种方式创建2种线程
类Thread:java对线程的抽象
Runnable: 对任务和业务逻辑的抽象
Thread threa = Thread(new Runnable())
线程如何中断?
Stop为什么不建议使用:会使线程立刻结束,而资源不会正常释放
Suspend()强制线程挂起,不会释放锁,可能会引起死索
Thread线程中断:
如果要中断线程,那么使用interrupt设置中断标志位
中断线程实现:
interrupt():对线程发起中断:并不是真正终止线程,给线程一个中断标志位(只是跟线程打招呼,线程不会立即停止,也可能不理会),线程是协作式,不是枪占式的(只是通知,但终止,由线程自已决定)
**isInterrupt() :**检测当前线程中断标志位是否true
**静态interrupted(),**检测当前线程中断标志位是否true,如果为true把中断标志位清除改成false
通常用interrupt()方法和isInterrupt结合使用中断线程,
在需要中断的情况下调用interrupt()设置标志位,用while(!interrupted()){ 处理逻辑};如果!interrupted()=false ,那么结束run方法,就可以达到线程中断的目的。
private class UserThread extends Thread{
public UserThread (String name) {
super(name);
}
@Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName+" interrrupt flag ="+isInterrupted());
while(!isInterrupted()){
System.out.println(threadName+" is running");
System.out.println(threadName+"inner interrrupt flag ="
+isInterrupted());
}
System.out.println(threadName+" interrrupt flag ="+isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
Thread endThread = new UseThread("endThread");
endThread.start();
Thread.sleep(20);
endThread.interrupt();//中断线程,其实设置线程的标识位true
}
不建议自己定义一cancel booble型去是否发起了中断。
因为如果在while(cancel){ 中调用waite();Thread.sleep(1000);阻塞类的方法} 那么while就会检测不到cancle=true。 但如果是用interrupt()设置标志位,waite();Thread.sleep(1000)方法检测到中断(如果发起了中断,方法底层会抛出interruptException异常,并把中断标识由true改成false),所以一定不建议自己定义cancel变量检测。
调用interrupt()后,会强制将sleep,wait (阻塞的线程)的线程,将行唤醒,也就是说interrupt()后,sleep的线程会抛出异常,所以我们在run里面可以捕获这个异常。
注意:如果run()方法里面调用了抛出InterruptException异常时,如果捕获了异常,那么注意要设置中断标志位,才可结束线程
public void run() {
while(!isInterrupted()) {
try {
Thread.sleep(100);//当中这个线程发起中断标志位时,会抛出异常并把中断标志位由true改成了false,可以在exception中调用interrupt()方法设置中断标志为true,那么while()条件interrupted检测到为true就结束循环,或可直接在异常中不理采
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+" in InterruptedException interrupt flag is "
+isInterrupted());
//资源释放(比如释放锁)
interrupt();//如果要在异常中中断异常,那么调用一次interrupt,将中断标志位设置成true,那么循环判断检测到为true,那么就会结束循环
e.printStackTrace();
}
}
}
为什么sleep(), 这阻塞方法,要抛出异常并设置重新设置false,
原因 1:可以在catch中检测到有
中断标志,如果不设置false,那么while会直接检测中断为true,就会结束,有可能有资源没释放,可能造成死锁,如果将中断位设置false,让我们在catch里面可先释放资源 才决定是否要中断线程
处于死锁状态线程,不会理会中断
Runnable接口实现中断
用:Thread.currentThread().isTnterrupted() 检测中断
While(!Thread.currentThread().isTnterrupted()){}
public class TestRunnable implements Runnable{
@Override
public void run()
String threadName = Thread.currentThread().getName();
while(Thread.currentThread().isInterrupted()) {
System.out.println(threadName+" is run!");
}
System.out.println(threadName+" interrput flag is "
+Thread.currentThread().isInterrupted());
}
}
public static void main(String[] args) throws InterruptedException {
TestRunnable testRunnable = new TestRunnable ();
Thread endThread = new Thread(testRunnable ,"endThread");
endThread.start();
Thread.sleep(20);
endThread.interrupt();
}
三、start() run()区别
Start() Run(),区别:
Start():有且仅能调用一次,启一个线程执行run()
Start()方法里面一开始会检测装态,如果已启动,那么抛异常。
Run(),不会启线程,无论调多少次都行
Jion()方法
如何保证2个方法顺序执行? 调用join()方法
Yiedld():让出cup执行权,不会让出锁
调用yield(),sleep(),wait(),notify(),对锁有何影响?
守护线程: jdk启动或设置守护线程 启动的就是守护线程,他是服务类线程,做一些后台调度和支持性工作,对内存的管理
用户线程结束后,守护线程就会结束;比如管理应用程 序的线程是守护线程,当应用执行完后,管理应用程序的守护线程也应结束。
注意:
一般在线程里面快束结的时候我们会在finally{}里面执行一释放资源操作,但是如果把一个线程改成守护线程后,finally{}里面的代码不一定会执行。
所以如果我们需要回收资源那么就不能设置成守护线程
来源:CSDN
作者:ccddsdsdfsdf
链接:https://blog.csdn.net/lh87270202/article/details/102559544