文章目录
多线程详解
线程就是独立执行的路径
main线程是主线程
线程创建
-
Thread class — 继承Thread类(重点)
-
Runnable接口 — 实现Runnable接口(重点)
-
Callable接口 — 实现Callable接口(了解即可)
Thread
继承Thread类,重写run()方法,调用start开启线程
//创建线程方式一:
public class TestThread01 extends Thread{
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 10; i++) {
System.out.println("看看代码-->"+i);
}
}
public static void main(String[] args) {
//创建一个线程对象
TestThread01 testThread01 = new TestThread01();
//调用start方法开启线程
testThread01.start();
// testThread01.run();
//main线程,主线程
for (int i = 0; i < 10; i++) {
System.out.println("学习线程-->"+i);
}
}
}
Runnable
实现Runnable接口,重写run()方法,执行接口需要丢入Runnable接口实现类,调用start方法
//创建线程方式二:
public class TestThread02 implements Runnable{
@Override
public void run() {
//run方法线程体
for (int i = 0; i < 10; i++) {
System.out.println("看看代码-->"+i);
}
}
public static void main(String[] args) {
//创建Runnable接口的实现类对象
TestThread02 testThread02 = new TestThread02();
//创建线程对象,通过线程对象来开启我们的线程,‘代理’
// Thread thread = new Thread(testThread02);
// thread.start();
new Thread(testThread02).start();
//main线程,主线程
for (int i = 0; i < 10; i++) {
System.out.println("学习线程-->"+i);
}
}
}
多个线程同时操一个对象
//买票例子
public class TestThread03 implements Runnable {
//票数
private int ticketNums = 10;
@Override
public void run() {
while (true){
if(ticketNums<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"-->拿到了第"+ticketNums--+"张票");
}
}
public static void main(String[] args) {
TestThread03 ticket = new TestThread03();
new Thread(ticket,"王宝强").start();
new Thread(ticket,"黄渤").start();
new Thread(ticket,"徐峥").start();
}
}
Callable
-
实现Callable接口,需要返回值类型
-
重写call方法,需要抛出异常
-
创建执行服务
-
提交执行
-
获取结果
-
关闭执行
静态代理
代理类和被真实类应该共同实现一个接口,或者是共同继承某个类。
Lambda表达式
-
避免匿名内部类过多
-
其实质属于函数式编程的概念
new Thread(( )-> System.out.println("i like lambda")).start();
-
前提是接口为函数式接口(interface)
public class TestLambda01 { public static void main(String[] args) { //lambda简化 ILove love = (int a)->{ System.out.println("i love you-->"+a); }; love.love(520); //简化1:参数类型 love = (a)->{ System.out.println("i love you-->"+a); }; love.love(521); //简化2:简化括号 love = a ->{ System.out.println("i love you-->"+a); }; love.love(522); //简化3:去掉花括号 love = a-> System.out.println("i love you-->"+a); love.love(523); } } interface ILove{ void love(int a); }
-
lambda表达式如果有多行,就用代码块包裹
停止线程
- 不推荐使用JDK提供的stop( )、destroy( )方法。【已废弃】
- 推荐线程自己停下来
- 建议使用一个标志位进行终止变量,当flag=flase,则终止线程运行
线程休眠(sleep)
-
sleep(时间)指定当前线程阻塞的毫秒数
-
sleep存在异常InterruptedException
-
sleep时间达到后线程进入就绪状态
-
sleep可以模拟网络延时,倒计时等
-
每一个对象都有一个锁,sleep不会释放锁
-
//模拟延时 try { Thread.sleep(100); }catch (InterruptedException e){ e.printStackTrace(); }
-
//模拟倒计时 public class TestSleep { public static void main(String[] args) { try { Tendown(); } catch (InterruptedException e) { e.printStackTrace(); } } public static void Tendown() throws InterruptedException{ int num = 10; while (true){ Thread.sleep(1000); System.out.println(num--); if (num<=0){ break; } } } }
线程礼让(Yield)
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转换为就绪状态
- 让CPU重新调度,礼让不一定成功,看CPU心情
线程强制执行(Join)
-
Join合并线程,待此线程执行完成后,再执行其他线程,其他线程堵塞
-
可以看成插队
-
public class TestJoin implements Runnable{ @Override public void run() { for (int i = 0; i < 10; i++) { System.out.println("线程vip来了"+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 < 100; i++) { if (i == 20){ thread.join(); } System.out.println("main"+i); } } }
守护(daemon)线程
-
线程分为用户线程和守护线程
-
虚拟机必须确保用户线程执行完毕
-
虚拟机不用等待守护线程执行完毕
-
//守护线程 //上帝保佑你 public class TestDaemon { public static void main(String[] args) { God god = new God(); You you = new You(); Thread thread = new Thread(god); thread.setDaemon(true);//默认是false,表示用户线程,正常线程都是用户线程 thread.start(); //上帝守护线程启动 new Thread(you).start(); //你 用户线程启动 } } //上帝 class God implements Runnable{ @Override public void run() { while (true){ System.out.println("上帝保佑着你!"); } } } //你 class You implements Runnable{ @Override public void run() { for (int i = 0; i < 365; i++) { System.out.println("你开心的活着!"); } System.out.println("====goodbye world===="); } }
线程同步机制
- 并发(同一个对象被多个线程同时操作)
- 队列 和 锁(synchronized)
死锁
- 死锁:多个线程互相抱着对方需要的资源,形成僵持
- 程序中要避免死锁
- 这是会产生死锁的情况
-
这是避免死锁的情况
Lock锁
class A{
private final ReentrantLock lock = new ReentrantLock();
public void m(){
lock.lock(); //加锁
try {
//保证线程安全的代码
}finally {
lock.unlock(); //解锁
//如果同步代码有异常,要将unloc()写入finally语句块
}
}
}
ReentrantLock:可重入锁
Lock锁与synchronized锁的对比
- Lock是显式锁,synchronized是隐式锁
- Lock只有代码块锁,synchronized有代码块锁和方法锁
- 使用Lock锁,JVM使用较少的时间来调度线程,性能更好
线程池
-
创建多个线程放入线程池中,使用时直接获取,使用完放回池中。
-
避免频繁创建销毁,实现重复利用
-
好处
- 提高响应速度
- 降低资源消耗
- 便于线程管理
-
import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; //线程池 public class TestPool { public static void main(String[] args) { //1.创建线程池 //newFixedThreadPool 参数为:线程池大小 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()); } }
这里是果力成,欢迎你的到来阅读,持续学习!
帅的人已经点点关注了~~