资讯详情

《Java并发编程从入门到入土(一):线程基础与生命周期》

📅 2026/9/12 19:48:21 | 华诺云谱 👁 阅读
《Java并发编程从入门到入土(一):线程基础与生命周期》
为什么需要线程餐厅里只有一个厨师单线程点餐的人多了后面的顾客要等很久。于是老板雇了多个厨师多线程每个人负责一桌菜效率大大提高。核心观点多线程的本质是提高CPU利用率让程序同时做多件事。为啥要有线程首先并发编程称为“刚需”单核 CPU 的发展遇到了瓶颈. 要想提⾼算⼒, 就需要多核 CPU. ⽽并发编程能更充分利⽤多核 CPU 资源。虽然多进程也能实现并发编程但线程比进程更加轻量创建线程比创建进程更快销毁线程比销毁进程更快调度线程比调度进程更快最后虽然线程更轻量但人们还不满足于是又有了“线程池”和“协程”。目前不做讨论线程和进程的区别进程包含线程每个进程至少有一个线程存在即主线程进程和进程之间不共享空间但同一个进程里的线程共享一个内存空间进程是系统资源分配的最小单位线程是资源调度的最小单位⼀个进程挂了⼀般不会影响到其他进程. 但是⼀个线程挂了, 可能把同进程内的其他线程⼀起带走(整个进程崩溃)创建线程1.继承Thread重写run为什么不import包也能导入Thread类这是因为java.lang自动会导入包。这个方法是创建一个线程类继承Thread通过重写run方法实现自己的逻辑用到了向上转型相当于有两个线程一个是main方法主线程另一个是MyThreadclass MyThread extends Thread{ //run相当于线程的入口 Override public void run() { System.out.println(hello thread); } } public class demo1 { public static void main(String[] args) { Thread tnew MyThread(); //start方法使线程t运行 t.start(); } }当在两个线程内部加上死循环时运行效果会发现两个线程都在抢内存资源分配。这时候调用Thread里面的sleep方法sleep是Thread类方法可以让当前线程短暂的退出内存资源的分配。2.实现Runnable接口重写runclass MyRunnable implements Runnable{ Override public void run() { while(true){ System.out.println(hello thread); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } } public class demo2 { public static void main(String[] args) { Runnable runnablenew MyRunnable(); Thread tnew Thread(runnable); t.start(); while(true){ System.out.println(hello main); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }实际上这里的runnable就是一个任务也就是一段要执行的逻辑最终还是要通过Thread来真正的创建线程其实这两个方法是差不多的关键的区别是执行任务的逻辑是放在Thread里面还是外面Runnable3.匿名内部类Thread本质上就是方法一使用匿名内部类这种方法的好处是可以少定义一些类如果某些代码是“一次性的”就可以使用匿名内部类的写法。public static void main(String[] args) throws InterruptedException { Thread tnew Thread(){ 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); Thread.sleep(1000); } }匿名内部类里做了三件事跟在new Thread后相当于创建了一个Thread的子类但是子类的名字不知匿名{}里可以定义子类的逻辑代码创建了匿名内部类的实例并把实例的引用赋值给t4.匿名内部类Runnable使用Runnable任务和线程的概念是分离的更好的达到了解耦合的思想public static void main(String[] args) throws InterruptedException { Runnable runnablenew Runnable(){ Override public void run() { while(true){ System.out.println(hello therad); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } } }; Thread tnew Thread(runnable); t.start(); while(true){ System.out.println(helllo main); Thread.sleep(1000); } }在Runnable里匿名内部类是在new Runnable()后即创建了一个创建了Runnable接口的实现类5.引入lambda表达式这个本质上就是作为匿名函数最主要的也是回调函数。-{}可以代表run方法public static void main(String[] args) throws InterruptedException { Thread tnew Thread(()-{ 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); } }Thread的几个常见属性首先ID属性相当于java会给每个运行的线程分配id类似于PID这个Deamon相当于“守护”守护线程也就是后台线程不能影响线程的存在与否。关于后台线程需要记住一点JVM会在⼀个进程的所有非后台前台线程结束后才会结束运行咱们代码创建的线程包括main线程都默认是前台线程可以通过setDaemon来设置注意看 main线程设置为执行三次后结束当main线程结束后thread线程仍然在在执行。因为二者都是前台线程前台线程会影响进程的结束而这种⬇️//thread默认是前台线程 public static void main(String[] args) { //匿名内部类 Thread tnew Thread(()-{ while(true){ System.out.println(hello thread); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); //设置后台线程时必须在start之前 t.setDaemon(true); t.start(); for (int i 0; i 3; i) { System.out.println(hello main); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } System.out.println(main线程结束); }main线程是前台线程它结束意味着整个进程结束public static void main(String[] args) throws InterruptedException { Thread t new Thread(() - { for (int i 0; i 3; i) { System.out.println(hello thread); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } }); // 这个结果一定是 false. // 此时还没有调用 start, 没有真正创建线程. System.out.println(t.isAlive()); t.start(); while (true) { System.out.println(t.isAlive()); Thread.sleep(1000); } }java中创建的Thread对象和系统中的线程是一一对应的关系但是Thread对象的声明周期和系统中线程的生命周期不同即可能存在Thread对象还存活但是系统中的线程已经销毁的情况对于lambda表达式来说他是在系统定义好线程之后才执行但它的定义是在new thread之后也就是说lambda表达式是先定义不执行等线程创建好之后在执行有了上面的知识这样写系统会报错也就不能这样写了⬇️换一种方式~ isInterrupted默认是返回false判断线程是不是被终止了public static void main(String[] args) throws InterruptedException { Thread tnew Thread(()-{ while(!Thread.currentThread().isInterrupted()){ System.out.println(hello thread); try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } } System.out.println(t结束); }); t.start(); Thread.sleep(3000); System.out.println(main线程尝试终止t线程); t.interrupt(); }isInterrupted()实例方法判断当前线程是否被中断不会清除中断标志位。Thread.interrupted()静态方法判断当前线程是否被中断会清除中断标志位重置为 false。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。