多线程基础
多线程基础
线程简介
-
线程
CPU调度和执行的单位
-
进程
系统资源分配的单位
-
多线程
一般为CPU的个数
线程创建
-
Thread---继承
-
自定义线程类继承Thread类
-
重写run()方法,编写线程执行体
-
创建线程对象,调用start()方法进行调用
public class TestThread extends Thread{ @Override public void run() { //run方法 for (int i = 0; i < 20; i++) { System.out.println("测试多线程==="); } } public static void main(String[] args) { TestThread testThread = new TestThread(); testThread.start(); for (int i = 0; i < 2000; i++) { System.out.println("主线程===="); } } }
不建议使用:避免OOP单继承局限性
-
-
Runnable--实现
-
定义类实现Runnable接口
-
实现run()方法,编写线程执行体
-
创建线程对象,调用start()方法启动线程
public class TestThread2 implements Runnable { @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println("测试多线程==="); } } public static void main(String[] args) { TestThread2 testThread2 = new TestThread2(); //实现方法1 Thread thread = new Thread(testThread2); thread.start(); //实现方法2 new Thread(testThread2).start(); for (int i = 0; i < 2000; i++) { System.out.println("主线程==="); } } }
推荐使用:避免单继承局限性,灵活方便,方便同一个对象被多个线程使用
-
-
Callable---实现
-
实现Callable接口,需要返回值类型
-
重写call方法,需要抛出异常
-
创建目标对象
-
创建执行服务:
ExecutorService ser = Executors.newFixedThreadPool(1)
; -
提交执行:
Future<Boolean> result = ser.submit(t1);
-
获取结果:
boolean r1 = result.get();
-
关闭服务:
ser.shutdownNow()
import java.util.concurrent.*; public class TestThread4 implements Callable<Boolean> { @Override public Boolean call() throws Exception { System.out.println("--->多线程: " + Thread.currentThread().getName()); return true; } public static void main(String[] args) throws ExecutionException, InterruptedException { TestThread4 t1 = new TestThread4(); TestThread4 t2 = new TestThread4(); TestThread4 t3 = new TestThread4(); //开启固定线程池 ExecutorService service = Executors.newFixedThreadPool(3); //提交线程 Future<Boolean> r1 = service.submit(t1); Future<Boolean> r2 = service.submit(t2); Future<Boolean> r3 = service.submit(t3); //获取结果 boolean rs1 = r1.get(); boolean rs2 = r2.get(); boolean rs3 = r3.get(); //关闭线程池 service.shutdownNow(); } }
-
静态代理---线程底层原理
- 真实对象和代理对象实现同一个接口
- 代理对象代理真实对象
- 好处:真实对象做自己的事情,代理对象做一些额外的事情
Lambda表达式
-
外部类
-
静态内部类
-
局部内部类
-
匿名内部类
-
lambda表达式
public class TestLambda { //2.静态内部类 static class Like2 implements Ilike { @Override public void lambda() { System.out.println("test lambda2"); } } public static void main(String[] args) { Ilike ilike = new Like(); ilike.lambda(); ilike = new Like2(); ilike.lambda(); //3.局部内部类 class Like3 implements Ilike { @Override public void lambda() { System.out.println("test lambda3"); } } ilike = new Like3(); ilike.lambda(); //4.匿名内部类,没有类的名称,必须借助接口或者父类 ilike = new Ilike() { @Override public void lambda() { System.out.println("test lambda4"); } }; ilike.lambda(); //5.lambda表达式 ilike = () -> { System.out.println("test lambda5"); }; ilike.lambda(); } } //定义抽象接口 interface Ilike { void lambda(); } //1.定义外部类 class Like implements Ilike { @Override public void lambda() { System.out.println("test lambda1"); } }
线程状态
-
创建状态
- new Thread进入创建状态
-
就绪状态
- 调用start()方法进入就绪状态,并不是立刻调度执行
-
阻塞状态
- 线程调用sleep,wait或者同步锁定时,线程进行阻塞状态
-
运行状态
- 线程真正执行,就绪状态调度
-
死亡状态
- 线程中断或者结束,进入死亡状态
-
方法
-
停止线程:定义标志位让线程停止
public class TestStop implements Runnable { private boolean flag = true; @Override public void run() { int i = 0; while (flag) { System.out.println("run...Thread" + i++); } } public void stop() { this.flag = false; } public static void main(String[] args) { TestStop testStop = new TestStop(); new Thread(testStop).start(); for (int i = 0; i < 1000; i++) { System.out.println("main" + i); if (i == 900) { testStop.stop(); System.out.println("线程停止"); } } } }
-
线程休眠
- sleep不会释放锁
-
线程让步
- 线程让步不一定成功,CPU重新调度
-
线程join
-
合并线程,线程执行完毕,在执行其它线程
public class TestJoin implements Runnable { @Override public void run() { for (int i = 0; i < 1000; i++) { System.out.println("join线程" + i); } } public static void main(String[] args) throws InterruptedException { TestJoin testJoin = new TestJoin(); Thread thread = new Thread(testJoin); thread.start(); for (int i = 0; i < 500; i++) { if (i == 200) { thread.join(); } System.out.println("main" + i); } } }
-
-
线程状态获取
-
Thread.State
import javax.swing.plaf.TableHeaderUI; public class TestState { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { for (int i = 0; i < 5; i++) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("---------"); }); Thread.State state = thread.getState(); System.out.println(state); thread.start(); state = thread.getState(); System.out.println(state); while (state != Thread.State.TERMINATED) { Thread.sleep(1000); state = thread.getState(); System.out.println(state); } } }
-
-
线程优先级
- 最小为1,最大为10
- 优先级高并不会一定最先运行
-
-
守护线程
- 用户线程默认
- 守护线程--需要设置,gc就是守护线程
线程同步
-
定义:一个对象被多个线程同时操作
-
形成条件:队列和锁
-
同步方法:synchronized关键字--默认锁this,锁的对象是变化的量
-
死锁:多个线程拿到对方需要的资源
-
Lock类:
ReentrantLock
(可重入锁)class A { private final ReentrantLock lock = new ReentrantLock(); public void run() { lock.lock(); try { //线程安全的代码 } finally { //将解锁放入finally代码块,防止线程安全的代码出现异常,一直持有锁 lock.unlock(); } } }
-
Lock和synchronized对比
- Lock是显式锁(手动开启关闭锁),synchronized是隐式锁,脱离作用域自动释放锁
- Lock只有代码块锁,synchronized有代码块和方法锁
- 使用Lock锁,JVM花费少的时间进行调度
- 使用顺序:Lock > 同步代码块 > 同步方法
线程通信问题
-
线程通信
wait()
等待其他线程通知,释放锁wait(long timeout)
指定等待时间释放锁notify()
唤醒一个处于等待状态的线程notifyAll()
唤醒所有等待状态的线程- 以上方法均是
Object
类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IIIegalMonitorStateException
-
管程法
//生产者消费者模型---利用缓冲区:管程法 //生产者,消费者,产品,缓冲区 public class TestPC { public static void main(String[] args) { SynContainer container = new SynContainer(); new Productor(container).start(); new Consumer(container).start(); } } //生产者 class Productor extends Thread { SynContainer container; public Productor(SynContainer container) { this.container = container; } //生产 @Override public void run() { for (int i = 0; i < 100; i++) { container.push(new Product(i)); System.out.println("生产了" + i + "个产品"); } } } //消费者 class Consumer extends Thread { SynContainer container; public Consumer(SynContainer container) { this.container = container; } //消费 @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("消费了--> " + container.pop().id + "个产品"); } } } class Product { int id; public Product(int id) { this.id = id; } } class SynContainer { //需要一个容器大小 Product[] products = new Product[100]; //容器计数器 private int count = 0; public synchronized void push(Product product) { //如果容器满了,需要等待消费者消费 if (count == products.length) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //如果没有满,放入产品 products[count] = product; count++; //通知消费者消费 this.notifyAll(); } public synchronized Product pop() { //判断是否能够消费 if (count == 0) { //等待生产者生产,消费者等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } //可以消费 count--; Product product = products[count]; //通知生产者生产 this.notifyAll(); return product; } }
-
信号灯法
public class TestPC2 { public static void main(String[] args) { Program program = new Program(); new Player(program).start(); new Watcher(program).start(); } } //生产者->演员 class Player extends Thread { Program program; public Player(Program program) { this.program = program; } @Override public void run() { for (int i = 0; i < 20; i++) { if (i % 2 == 0) { this.program.play("少年包青天"); } else { this.program.play("广告"); } } } } //消费者->观众 class Watcher extends Thread { Program program; public Watcher(Program program) { this.program = program; } @Override public void run() { for (int i = 0; i < 20; i++) { program.watch(); } } } //节目 class Program { //表演的节目 String voice; //演员表演为true,观众观看为false boolean flag = true; //表演 public synchronized void play(String voice) { if (!flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("演员表演了:" + voice); this.notifyAll(); this.voice = voice; this.flag = !this.flag; } //观看 public synchronized void watch() { if (flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("观众观看了:" + voice); this.notifyAll(); this.flag = !this.flag; } }
高级主题
-
线程池
-
ExecutorService
-
void excute(Runnable command)
执行任务,没有返回值 -
<T> Future<T> submit(Callable<T> task)
执行任务,有返回值 -
void shutdown()
关闭连接池import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestPool { public static void main(String[] args) { //创建线程池 ExecutorService service = Executors.newFixedThreadPool(10); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.execute(new MyThread()); service.shutdown(); } } class MyThread implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }
-
-