JavaSE(十一)
线程
1、什么是并发与并行
要想学习多线程,必须先理解什么是并发与并行:
并行:指两个或多个事件在同一时间点发生。
并发:指两个或多个事件在同一个时间段内发生。

2、什么是进程、线程
2.1进程
进程是正在运行的程序的实例。
比如打开一个浏览器、打开一个word等操作,都会创建进程。

2.2线程
进程是线程的容器,即一个进程可以同时并发运行多个线程;
比如进程可以理解为医院,线程是挂号、就诊、缴费、拿药等业务活动。

多线程:多个线程并发执行。
3、线程的创建
3.1继承Thread类
第一步:创建自定义线程类
package com.hg.Thread.creat;
import java.util.Date;
public class MyThread extends Thread{
//线程的业务
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("MyThread线程正在运行," + new Date().getTime());
}
}
}
第二步:创建测试类
注意:
1.新建的线程不会自动开始运行,必须通过start()方法启动线程
2.main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。
package com.hg.Thread.creat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//new MyThread().run();//程序从上往下执行
//自定义线程
//new MyThread().start(); //启动线程,等待cpu资源
//new Thread(new MyThread2()).start();
FutureTask<String> futureTask = new FutureTask<>(new MyThread3());
new Thread(futureTask).start();
//main线程
for (int i = 0; i < 10; i++) {
System.out.println("main线程正在执行," + new Date().getTime());
}
System.out.println(futureTask.get());
}
}
问题:java是单继承的,此时MyThread只能extendsThread类
3.2实现Runnable接口
第一步:创建自定义类实现Runnable接口
package com.hg.Thread.creat;
import java.util.Date;
public class MyThread2 implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("MyThread2线程正在运行:" + new Date().getTime());
}
}
}
第二步:创建测试类
package com.hg.Thread.creat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//new MyThread().run();//程序从上往下执行
//自定义线程
//new MyThread().start(); //启动线程,等待cpu资源
//new Thread(new MyThread2()).start();
FutureTask<String> futureTask = new FutureTask<>(new MyThread3());
new Thread(futureTask).start();
//main线程
for (int i = 0; i < 10; i++) {
System.out.println("main线程正在执行," + new Date().getTime());
}
System.out.println(futureTask.get());
}
}
问题:
1.没有返回值,不支持泛型的返回值
2.不可以抛出异常
3.3实现Callable接口
Callable需要使用FutureTask类帮助执行,FutureTask类结构如下:

第一步:创建自定义类实现Callable接口
package com.hg.Thread.creat;
import java.util.Date;
import java.util.concurrent.Callable;
public class MyThread3 implements Callable<String> {
@Override
public String call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println("MyThread3正在运行:" + new Date().getTime());
}
return "叶瞬光是我女朋友";
}
}
第二步:创建测试类
package com.hg.Thread.creat;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class ThreadTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//new MyThread().run();//程序从上往下执行
//自定义线程
//new MyThread().start(); //启动线程,等待cpu资源
//new Thread(new MyThread2()).start();
FutureTask<String> futureTask = new FutureTask<>(new MyThread3());
new Thread(futureTask).start();
//main线程
for (int i = 0; i < 10; i++) {
System.out.println("main线程正在执行," + new Date().getTime());
}
System.out.println(futureTask.get());
}
}
问题:频繁创建和销毁线程开销大
3.4线程池-ThreadPoolExecutor
线程池的核心概念:
线程池本质上是一个管理线程的容器,它预先创建一定数量的线程,当有任务需要执行时,直接从池中取出空闲线程来执行任务,避免频繁创建和销毁线程(线程的创建/销毁需要消耗CPU、内存等资源)。
Java线程池的核心参数:
public ThreadPoolExecutor(
int corePoolSize,//核心线程数
int maximumPoolSize,//最大线程数
long keepAliveTime,//空闲存活时间
TimeUnit unit,//时间单位
BlockingQueue<Runnable> workQueue,//任务队列
ThreadFactory threadFactory,//线程工厂
RejectedExecutionHandler handler//拒绝策略
)
这几个参数的作用:
| 参数 | 作用 |
|---|---|
| corePoolSize | 核心线程数:线程池长期保持的线程数量(即使空闲也不会销毁,除非设置allowCoreThreadTimeOut) |
| maximumPoolSize | 最大线程数:线程池允许创建的最大线程数 |
| keepAliveTime | 空闲超时时间:非核心线程空闲超过该时间会被销毁 |
| TimeUnit | 时间单位 |
| workQueue | 任务队列:核心线程都在忙时,新任务会先放入队列等待 |
| threadFactory | 线程工厂:自定义线程的创建方式(如设置线程名、优先级) |
| RejectedExecutionHandler | 拒绝策略:当任务数超过 “最大线程数 + 队列容量” 时,如何处理新任务(如抛异常、丢弃任务等) |
创建线程池:
package com.hg.Thread.creat.homeWork;
import java.util.concurrent.*;
public class Work2 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
3,
5,
10,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(2),
new ThreadFactory() {
int count = 1;
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("MyThread-" + count++);
return thread;
}
},
new ThreadPoolExecutor.CallerRunsPolicy()
);
poolExecutor.execute(new Thread2(1,10,200));
poolExecutor.execute(new Thread2(11,20,300));
poolExecutor.execute(new Thread2(21,30,100));
poolExecutor.shutdown();
System.out.println("所有子线程已启动,主线程继续执行");
}
static class Thread2 implements Runnable {
private Integer begin;
private Integer end;
private Integer millis;
public Thread2(Integer begin, Integer end, Integer millis) {
this.begin = begin;
this.end = end;
this.millis = millis;
}
@Override
public void run() {
for (int i = begin; i <= end; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Executors工具类:
Executors是JDK提供的一个线程池工具类(位于java.util.concurrent包下),它封装了
ThreadPoolExecutor的创建细节,提供了一系列静态工厂方法,让你可以快速创建各种类型的线程池,无需手动设置corePoolSize、workQueue等复杂参数。
package com.hg.Thread.creat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MyThread4 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
for (int i = 1; i <= 5; i++) {
int taskNum = 1;
executorService.execute(new Runnable() {
@Override
public void run() {
//Thread.currentThread().getName():获得当前线程名字
System.out.println(Thread.currentThread().getName() + "正在执行" + taskNum);
try {
Thread.sleep(1000); //线程休眠,阻塞1秒钟
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
executorService.shutdown();
}
}
4、Thread类的常用方法
4.1Thread类常用方法说明

4.2 join()方法
package com.hg.Thread.method;
public class JoinMethodTest {
public static void main(String[] args) throws InterruptedException {
JoinMethod joinMethod = new JoinMethod();
joinMethod.setName("joinMethod");
joinMethod.start();
Thread.currentThread().setName("主线程");
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
if (i == 2){
joinMethod.join();
}
}
}
}
class JoinMethod extends Thread{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(getName() + ": " + i);
}
}
}
4.3 sleep()方法
package com.hg.Thread.method;
public class SleepMethodTest {
public static void main(String[] args) throws InterruptedException {
Thread sleepMethod = new Thread(new SleepMethod());
sleepMethod.setName("sleepMethod");
sleepMethod.start();
Thread.currentThread().setName("主线程");
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
if (i == 2){
Thread.sleep(100);
}
}
}
}
class SleepMethod implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
4.4 yield()方法
package com.hg.Thread.method;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
public class YieldMethodTest {
public static void main(String[] args) {
Thread yieldMethod = new Thread(new FutureTask<>(new YieldMethod()));
yieldMethod.setName("YieldMethod");
yieldMethod.start();
Thread.currentThread().setName("主线程");
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
}
}
}
class YieldMethod implements Callable {
@Override
public Object call() throws Exception {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + ": " + i);
if (i == 2){
Thread.yield();
}
}
return null;
}
}更多推荐




所有评论(0)