1、进程与线程的概念
进程就是正在执行的程序,进程有自己独立的一块内存空间,一个进程中有一个或多个线程;线程是进程中的一个执行路径;以人的眼光看线程时,感觉是同时执行,但是实际上是cpu轮换执行。只是速度切换比较快,人感觉不到。举个例子,正在运行的360就是一个进程,如果同时开启电脑体检、木马查杀、电脑清理等就会出现多个执行任务,每个任务对应一个线程,感觉是同时在执行,其实是cpu轮换。属于同一进程的线程会共享同一个进程的资源:堆内存、方法区内存。好处:高效,方便。缺点:线程安全问题。
进程是操作系统进行调度和分配资源的基本单位,进程之间相互独立。
线程是CPU进行调度处理的最基本单位。
2、创建线程方式
2.1 继承Thread类,重写run(),创建对象,最后调用start()。
class T1 extends Thread{ public void run(){ //任务代码 } } public static void main(String[] args){ T1 t1 = new T1(); t1.start(); }
2.2实现Runnable接口
class MyThread implements Runnable{ public void run(){ 任务代码 } } public static void main(){ Thread t1 = new Thread(new MyThread()); t1.start(); }
2.3 实现Callable接口
public class CallableDemon { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<String> futureTask = new FutureTask(() -> { System.out.println("lambda 表达式....."); return "test2"; }); Thread thread = new Thread(futureTask); thread.start(); System.out.println("返回值是:" + futureTask.get()); } }
借助FutureTask构造器传入Callable实现类。
注意:(1)Callable是函数式接口
(2)call()方法,任务写在这
(3)如何获取返回值?
2.4 线程池
public class MyThreadPoolDemon { public static void main(String[] args) { //创建固定数量的线程池 //ExecutorService threadPool = Executors.newFixedThreadPool(5); //创建有一个线程的线程池 //ExecutorService threadPool = Executors.newSingleThreadExecutor(); //可扩展的线程池,不会用因为最大值太大 ExecutorService threadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { threadPool.execute(() -> { System.out.println(Thread.currentThread().getName()+"办理业务"); }); } } }
运行机制:https://www.jianshu.com/p/a900d4d101b7
3、线程的状态图
4、sleep()与wait()的区别?
(1)sleep是Thread类的静态方法,wait是Object类的方法。
(2)sleep是持锁的,当到达指定时间后,变为就绪态,一旦得到cpu就变为运行态;而wait是不持锁的,并且需要notify或者notifyAll()唤醒。
5、线程通讯
/* * 厨师,往工作台上放菜,当工作台放不了啦,就停止做菜并通知服务员取菜, * 工作台最多放10个菜, * 服务员从工作台取菜,当没有菜时就等待并通知厨师做菜。 */ public class TestCommunicate1 { public static void main(String[] args) { WorkBench w = new WorkBench(); Cook cook = new Cook(w); Waiter waiter = new Waiter(w); cook.start(); waiter.start(); } } class Cook extends Thread{ private WorkBench w; public Cook(WorkBench w) { this.w = w; } @Override public void run() { while (true) { w.put(); } } } class Waiter extends Thread{ private WorkBench w; public Waiter(WorkBench w) { this.w = w; } @Override public void run() { while(true){ w.take(); } } } class WorkBench{ private int num;//记录菜的数量 public static final int MAX_NUM = 10;//工作台最多放10个菜 //放菜方法(需要线程安全) public synchronized void put(){ //当工作台放满10个菜,本线程需要等待,并通知服务员来取菜 while(num >= MAX_NUM) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } num++; try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("厨师放了一道菜,工作台还有"+num+"个菜"); this.notify(); } //取菜方法 public synchronized void take(){ while (num <= 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } num--; try { Thread.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("服务员端走一盘菜,工作台还有"+num+"个菜"); this.notify(); } }