前言:
一、什么是进程?
正在运行的程序的实例
在操作系统没有引入进程的时候,CPU每次只能执行一个程序多个程序只能顺序执行,这样就造成了资源的浪费浪费了大量的时间,为了提高CPU的利用率于是操作系统引入了进程以及中断处理,这样就实现了通一时间内可以运行多个程序提高效率。
资源分配基本单位
二、什么是线程?
进程的实际运行最小单位
进程虽然实现了并发编程但是平凡创建进程的开销较大,引入的线程是轻量级的进程,可以减少开销提高效率。
调度执行的基本单位
一、线程创建:
- 继承Thread类实现的run方法
- 实现Runnable接口重写里面run方法
- 继承Thread类实现run方法,匿名内部类实现
- 使用匿名内部类重写run方法
- lambda表达式
继承Thread类实现的run方法
class MyTread extends Thread { public void run() { while (true) { System.out.println("Hello Thread "); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Demo1 { public static void main(String[] args) throws InterruptedException { MyTread myTread = new MyTread(); myTread.start(); while ( true) { System.out.println("Hello main"); Thread.sleep(1000); } } }
实现Runnable接口重写里面run方法
class MyRunnable implements Runnable{ @Override public void run() { while (true) { System.out.println("Hello Runnable"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class Demo2 { public static void main(String[] args) throws InterruptedException { MyRunnable myRunnable = new MyRunnable(); Thread t = new Thread(myRunnable); t.start(); while (true) { System.out.println("Hello main"); Thread.sleep(1000); } } }
继承Thread类实现run方法,匿名内部类实现
public class Demo3 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread() { public void run() { while (true) { System.out.println("Hello Thread"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }; t.start(); while (true) { System.out.println("Hello main"); Thread.sleep(1000); } } }
使用匿名内部类重写run方法
public class Demo4 { public static void main(String[] args) { Thread t = new Thread(new Runnable() { @Override public void run() { while (true) { System.out.println("Hello Thread"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }); t.start(); while (true) { System.out.println("Hello main"); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
lambda表达式
public class Demo5 { public static void main(String[] args) { Thread t = new Thread(() -> { while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("Hello Thread"); } }); t.start(); } }
二、线程中断
常用三个方法
public void interrup()
作用:中断调用方法的线程,调用方法后线程仍然运行,只是标志位改为true(中断状态)
public static boolean interred()
作用:检测当前线程是否中断,返回一个boolean并且清除当前线程状态,第二次调用返回false
public boolean isInterrupted()
作用:检测调用方法的线程是否中断,不清除状态
三、线程等待
public void join()
编辑
大家看下这个例子:
public class test { public static final long count = 10_0000_0000L; public static void main(String[] args) throws InterruptedException { serial(); long begin =System.currentTimeMillis(); Thread t1 = new Thread(() ->{ long a =0; for (long i = 0; i < count; i++) { a++; } }); Thread t2 = new Thread(() ->{ long a = 0; for (long i = 0; i < count; i++) { a++; } }); t1.start(); t2.start(); t1.join(); t2.join(); long end = System.currentTimeMillis(); System.out.println("多线程时间:" + (end-begin)); } public static void serial() { long a =0; long begin = System.currentTimeMillis(); for (int i = 0; i < count; i++) { a++; } a=0; for (int i = 0; i < count; i++) { a++; } long end = System.currentTimeMillis(); System.out.println("单线程所用时间:" +(end - begin)); }
这里面使用了t1.join()和t2.join(),作用是让当前线程(这里是main主线程)等待使用join方法的线程执行完成再进行当前线程。join方法会将当前线程从执行的线程中挂起,挂到等待队列中等到线程执行完成后再从等待队列加入到执行队列中。
编辑补充:
使用带参数的join方法叫做期限等待(TIME_WAITING):在这种状态下不会被CPU分配执行实现,无需等待被其他线程显式唤醒,在时间结束后即可自动唤醒。
四、线程休眠
sleep() 定义在Thread.java中。
sleep() 的作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。线程在休眠期间会让出cpu资源。在线程休眠之后,可以在任意时间对线程进行唤醒。
五、线程状态
新建(NEW):创建出线程但是没有启用。
运行状态(RUNNABLE):调用start方法启用线程,此时线程实在执行状态
无限等待状态(WATING):这种状态下不会被CPU分配执行时间,等到被唤醒。
无Timeout参数的Object.wait()方法
无Timeout参数的Thread.join()方法
LockSupport.park()方法
期限等待(TIME_WAITING):在这种状态下不会被CPU分配执行实现,无需等待被其他线程显式唤醒,在时间结束后即可自动唤醒。
堵塞状态(BLOCKED):线程被堵塞
结束(TERMINATED):线程执行结束