《线程(一)》
目录
一、线程概念
程序、进程、线程
程序:一堆命令的集合,进程的静止的状态,包括了可执行文件、配置文件、数据文件等等软件文件集合;
进程:程序运行期间的动态状态,占用内存、占用CPU等系统资源;
线程:进程下的最小的执行单元,多任务处理的最基本的执行单元。

主线程
在Java程序启动时,一个线程立刻运行,该线程通常称为程序的主线程;主线程的重要性体现在两个方面:
- 它是产生其他子线程的线程(但不一定负责关闭子线程);
- 通常它必须最后完成执行(除了守护线程之外),因为它执行各种关闭动作。

多线程
- 在Java中,一个应用程序可以包含多个线程。每个线程执行特定的任务,并可与其他线程并发执行;
- 多线程使系统的空转时间最少,提高CPU利用率;
- 多线程编程环境用方便的模型隐藏CPU在任务间切换的事实。
二、线程创建
主线程测试(main)
package com.hpr.test;
public class Test {
public static void main(String[] args) {
Thread t = Thread.currentThread();
System.out.println("当前线程:" + t.getName());
t.setName("主线程");
System.out.println("当前线程:" + t.getName());
}
}
执行结果

多线程应用(场景模拟)
果园要出口水果,用户下单要10W苹果跟10W梨,这个时候安排工作人员去装箱。

案例一(单线程处理)
package com.hpr.test;
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
//装苹果
List<String> appleList = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
appleList.add("apple" + i);
}
//装梨
List<String> pearList = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
pearList.add("pear" + i);
}
System.out.println("单线程:10W苹果+10W梨装箱完成!");
}
}
执行结果

线程创建方式
- 继承Thread类,重写run方法
- 实现Runnable接口,实现run方法
案例二(多线程处理)
- TestThread类
package com.hpr.test;
import java.util.ArrayList;
import java.util.List;
public class TestThread {
/**
* 苹果线程
*/
static class AppleThread extends Thread {
@Override
public void run() {
List<String> appleList = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
appleList.add("apple" + i);
}
System.out.println(Thread.currentThread().getName() + ":10W苹果装箱完成!");
}
}
/**
* 梨线程
*/
static class PearThread implements Runnable {
@Override
public void run() {
List<String> pearList = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
pearList.add("pear" + i);
}
System.out.println(Thread.currentThread().getName() + ":10W梨装箱完成!");
}
}
public static void main(String[] args) {
AppleThread th1 = new AppleThread();
th1.setName("苹果线程");
th1.start();
Thread th2 = new Thread(new PearThread());
th2.setName("梨线程");
th2.start();
System.out.println(Thread.currentThread().getName() + ":正在执行...");
}
}
执行结果
多线程默认情况下是异步的(即各做各的)。

加入线程(优先执行)
修改上述代码:
public static void main(String[] args) {
...
try {
//加入线程(优先执行)
th1.join();
th2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":正在执行...");
}
执行结果

三、线程状态
Thread重要方法
void start() //启动线程
void setPriority(int p) //设置线程优先级1~10
void interrupt() //有条件中断线程
void sleep(long s) //线程休眠,可指定让出cpu资源时长
Thread currentThread() //获取执行当前内容的线程
boolean isAlive() //判断线程是否在活动状态
void yield() //临时让出cpu资源
void setDaemon(boolean b) //设置是否是守护线程
void join() //加入其他线程,即优先执行
void wait() //Object方法,使当前线程处于等待状态
void notify() //Object方法,随机唤醒一个等待状态线程
void notifyAll() //Object方法,唤醒所有等待状态线程
Thread状态
- 新建 (Born) : 新建的线程处于新建状态;
- 就绪 (Ready) : 在创建线程后,它将处于就绪状态,等待 start() 方法被调用;
- 运行 (Running) : 线程在开始执行时进入运行状态;
- 睡眠 (Sleeping) : 线程的执行可通过使用 sleep() 方法来暂时中止。在睡眠后,线程将进入就绪状态;
- 等待 (Waiting) : 如果调用了 wait() 方法,线程将处于等待状态。用于在两个或多个线程并发运行时;
- 挂起 (Suspended) : 在临时停止或中断线程的执行时,线程就处于挂起状态;
- 恢复 (Resume) : 在挂起的线程被恢复执行时,可以说它已被恢复;
- 阻塞 (Blocked) – 在线程等待一个事件时(例如输入/输出操作),就称其处于阻塞状态;
- 死亡 (Dead) – 在 run() 方法已完成执行或其 stop() 方法被调用之后,线程就处于死亡状态。
四、结束线程
结束线程就是让线程的run方法执行完毕,而不是使用stop()或者destroy()方法,可使用以下三种方式:
- 修改标志
- interrupt()
- 引发异常
修改标志(适用于无阻塞线程)
package com.hpr.test;
public class Test1 {
static class OverThread extends Thread {
//标志变量,默认为true
boolean flag = true;
//提供外部设置方法
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
int i = 0;
while (flag) {
try {
Thread.sleep(1000);
System.out.println(i++);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("子线程运行结束!");
}
}
public static void main(String[] args) {
//启动子线程
OverThread th = new OverThread();
th.start();
try {
//主线程休眠3秒后修改子线程标志为false
Thread.sleep(3000);
th.setFlag(false);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
执行结果

interrupt打断(适用于休眠或等待线程)
//此类线程只要调用interrupt()方法就可以终止线程
public void run() {
while (!this.isInterrupted()) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
}
}
引发异常(适用于阻塞,如监听连接、文件流操作)
public void run() {
byte[] b = new byte[1024];
while (true) {
try {
//is是输入流
int len = is.read(b);
//其他代码
} catch (IOException e) {
//发生异常,打断循环,线程也就结束了
break;
}
}
}
总结
重点
- 程序、进程、线程相关概念;
- 主线程与多线程;
- 线程相关方法及状态;
- 结束线程的三种方式。
难点
- 线程相关方法及状态。
本文介绍了Java中的线程概念,包括程序、进程和线程的区别。详细讲解了主线程以及多线程的应用,通过装箱水果的场景模拟展示了单线程和多线程的执行差异。同时,文章提到了线程的创建方式,如继承Thread类和实现Runnable接口,并讨论了线程状态和结束线程的策略,包括修改标志、interrupt方法和引发异常。
303

被折叠的 条评论
为什么被折叠?



