线程与进程
线程 是进程中的执行过程,一个进程包含有多个线程,并发执行
进程 是一个运行的应用程序,每个进程都有自己独立的内存空间。在Windows系统中,一个运行的exe(应用程序)就是一个进程
实现线程
实现线程线程主要有 java.lang.Thread类 与 Runnable接口
Thread类
Class Thread
java.lang.Object
java.lang.Thread
Thread类中实例化的对象代表线程,启动需要Thread实例
常用构造方法
Thread()
Thread(String name)
name: 自定义线程名
常用方法
修饰符 | 方法 | 说明 |
---|---|---|
Thread | currentThread() | 返回对当前正在执行的线程对象的引用 |
long | getId() | 返回线程标识符 |
String | getName() | 返回线程名称 |
int | getPriority() | 返回线程的优先级 |
Thread.State | getState() | 返回线程的状态 |
void | interrupt() | 中断线程 |
boolean | isAlive() | 线程是否运行 |
boolean | isInterrupted() | 线程是否被中断 |
void | run() | 调用该Runnable对象的run方法 |
void | start() | 线程开始执行run方法 |
void | sleep(long ms) | 线程以指定的毫秒数暂停(等待) |
void | join() | 在线程中加入另一个线程 |
boolean | interrupted() | 中断线程 |
void | setPriority(int newPriority) | 设置线程的优先级newPriority的范围(1-10) |
void | setDaemon(boolean on) | 是否设置守护线程。守护线程:主线程结束,子线程也跟着结束 |
String | toString() | 返回线程的字符串表示、线程的名、优先级、线程组 |
Runnable接口
线程一般通过Thread类创建的。但 Runnable接口 也可以实现进程

优点
- 适合多线程同时执行相同的任务
- 不受 类的单继承约束
实现方式
Thread(Runnable target)
Thread(Runnable target , String name)
target: 启动线程时调用,run方法
name: 自定义线程名
Callable接口
Runnable接口 比 Callable接口 少了 线程结束无返回值 和 不能抛出异常 ,而 Callable接口 正是弥补这一缺陷!
使用步骤
//1. 编写 Callable接口 , 实现 call抽象方法
class MyCallable implements Callable<T>{
@Ovrride
public <T> call() throws Exception{
return T;
}
}
//2. 创建FutureTask对象,并传入第一步编写的Callable类对象
FutureTask<T> future = new FutureTask<>(callable);
//3. 通过Thread,启动线程
new Thread(future).start();
//4. 获取返回值,FutureTask对象中的get()方法获取返回值(此方法有堵塞效果)
future.get();
FutureTask类 说明:用于异步获取执行结果或取消执行任务的作用(线程池的核心)
线程生命周期
线程具有生命周期,有7种分别为:出生状态、就绪状态、运行状态、休眠状态、阻塞状态、死亡状态
周期的说明:
出生状态(New): 线程创建后到线程的start()方法前
就绪状态(Runnable): 可执行状态,当线程获取系统资源就进入运行状态
运行状态(Running): run()方法,没有意外线程则一直运行到结束
休眠状态(Sleep): 执行sleep()方法休眠(等待)
阻塞状态(Blocked): 等待用户 输入/输出 ,用户 输入/输出 结束后进入就绪状态
死亡状态(Dead): 线程的run()方法执行完毕,则进入死亡状态

Windows操作系统中,会为每个线程分配一小段CPU时间片,一旦CPU时间片结束会切换到下一线程
再次进入运行状态:
- 线程调用notify()方法(唤醒线程)
- 线程调用notifyAll()方法(唤醒线程)
- 线程调用interrupt()方法(中断线程)
- 线程的休眠时间结束
- 输入/输出 结束
线程方法
线程休眠
sleep(long ms) 方法 停止多少秒。它可能会抛出InterruptedException异常,所以放在try-catch块中。暂停后醒来,不能保证它能立即运行!
//休眠1s
Thread.sleep(1000);
线程加入
join() 方法 加入线程。当一个线程执行中,join()方法可使另一个线程加入,线程需要等另一个线程执行完才可以继续执行原旧的线程!
join(long millis , int nanos)
millis: 等待另一个线程的时间(秒
nanos: 另一个线程的死亡时间(纳秒
//加入ThreadB线程
··· run(){
//线程执行中
while(true){
//加入另一个线程
ThreadB.join();
}
}
线程中断
interrupted() 方法 中断线程。 能使线程离开run()方法,同时结束线程,但会抛出InterruptedException异常!
//终止线程:ThreadA
ThreadA.interrupted();
唤醒线程
notify()
唤醒正在等待的单个线程
notifyAll()
唤醒正在等待的所有线程
wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法
wait/notify方法的调用必须处在该对象的锁中,在调用这些方法时首先需要获得该对象的锁,需要配合同步使用,以防多线程错乱
线程礼让
yield() 方法 线程礼让,给当前运行状态的线程提个醒,告知它可以将资源礼让给其他线程。但目前情况没有机制能保证当前线程会礼让将资源分配!(操作系统会自动分配CPU时间片执行 (不常用
线程优先级
每个线程都有自己的优先级,线程的优先级代表着该线程的重要性。多个处于就绪的线程就能体现优先级的作用!
Thread类中包含成员变量代表有:
Thread.MAX_PRIORITY = 10 (常量10
Thread.MIN_PRIORITY = 1 (常量1
Thread.NORM_PRIORITY = 5 (默认5
setPriority(int newPriority) 方法 进程优先级调整。调整线程的优先级的情况newPriority范围(0-10)
线程同步
多线程执行程序,会出现线程抢资源的现象,该现象会导致数据脏读!为了防止多线程的冲突,JAVA提供了线程同步的机制来防止资源抢占的问题!
synchronized关键字
synchronized关键字采用定时只允许一个线程访问共享资源 (道理跟上排队上厕所一样
同步块
每个对象都有标志位,它具有0和1两个值。0代表同步块中在运行其他线程;1代表该线程能被同步块执行,执行中途并将Object对象的标志位设置为0,防止其他线程执行同步块中的代码。(一个线程运行到同步块时首先检查该对象的标志位)
synchronized(Object){
···
}
//Object:任意对象,仅作为标志(相当于一把锁,多人使用的锁)
同步方法
在自定义方法 前面修饰 synchronized关键字 形成同步方法。
某对象调用同步方法时,该对象的其他同步方法必须等待该同步方法执行完毕后才能被执行。必须将每个能访问共享资源的方法修饰为synchronized,否则会报错!
显示锁
Class ReentrantLock
java.lang.Object
java.util.concurrent.locks.ReentrantLock实现接口
Serializable , Lock
ReentrantLock
和 synchronized
又 称隐式锁 或 显示锁,它们在使用上没有什么区别 ,但ReentrantLock
可更直观的体现锁的概念。 synchronized
则是隐式实现锁的概念。
构造方法
ReentrantLock()
ReentrantLock(boolean fair)
fair: 公平锁
方法
返回 | 方法 | 说明 |
---|---|---|
int | getHoldCount() | 查询当前线程对锁的停止数量 |
int | getQueueLength() | 获取锁的线程数 估数 |
int | getWaitQueueLength(Condition condition) | 获取与此锁相关条件等待的线程 |
boolean | hasQueuedThread(Thread thread) | 查询指定线程是否获取锁 |
boolean | hasQueuedThreads() | 查询是否有线程等待锁 |
boolean | hasWaiters(Condition condition) | 查询是否有相关条件等待的锁 |
boolean | isFair() | 是否为锁的公平,启动则true |
boolean | isHeldByCurrentThread() | 查询锁是否是当前线程持有 |
boolean | isLocked() | 查询锁是否有线程持有 |
void | lock() | 锁定锁(上锁) |
void | lockInterruptibly() | 锁定锁 |
String | toString() | 返回标识锁的字符串内容 |
boolean | tryLock() | |
boolean | tryLock(long timeout, TimeUnit unit) | 指定时间范围, |
void | unlock() | 释放锁(解锁) |
线程池
ExecutorService接口
继承接口
Executor实现类
AbstractExecutorService , ForkJoinPool , ScheduledThreadPoolExecutor , ThreadPoolExecutor
线程的集合称为线程池
频繁多线程操作会影响效率。反复的 创建 、关闭 线程会需要大量时间!可减少时间 和 资源的浪费!
线程池原理图

缓存线程池
- 无长度限制
- 自动扩容空间
定长线程池
- 自定 固定 长度
- 无闲线程 空间未满 自动扩容
- 无闲线程 空间已满 等待空闲
单线程线程池
- 只有一个线程
- 无闲线程 等待
周期性任务定长线程池
- 可指定长度
- 无闲线程 空间未满 自动扩容
- 无闲线程 空间已满 等待空闲
- 定时执行、周期执行
代码索引
File操作
public class Demo {
public static void main(String[] args) {
//实例对象
Thread a = new MyThreadA();
Thread b = new MyThreadB();
/**其他方法测试*/
System.out.println("==========");
System.out.println("a.getId():"+a.getId());
System.out.println("a.getName():"+a.getName());
System.out.println("a.getPriority():"+a.getPriority());
System.out.println("a.getState():"+a.getState());
System.out.println("a.isAlive():"+a.isAlive());
System.out.println("a.isInterrupted():"+a.isInterrupted());
System.out.println("a.toString():"+a.toString());
System.out.println("==========");
//执行线程(双线程执行,同时执行)
/**线程A*/
a.start();
/**线程B*/
b.start();
/**
以下代码为运行a对象的run()方法再执行b对象run()方法
a.run();
b.run();
*/
}
}
class MyThreadA extends Thread{
@Override
public void run() {
for (int i = 0; i < 26; i++) {
System.out.print("A:"+i);
/**休眠1秒(等待)*/
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThreadB extends Thread{
@Override
public void run() {
for (char i = 'a'; i < 'z'; i++) {
System.out.println("B:"+i);
/**休眠1秒(等待)*/
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**运行结果
==========
a.getId():13
a.getName():No.1
a.getPriority():5
a.getState():NEW
a.isAlive():false
a.isInterrupted():false
a.toString():Thread[No.1,5,main]
==========
B:a
A:0
B:b
A:1
B:c
A:2
A:3
B:d
B:e
A:4
A:5
B:f
A:6
B:g
A:7
B:h
A:8
B:i
B:j
A:9
A:10
B:k
A:11
B:l
A:12
B:m
B:n
A:13
A:14
B:o
B:p
A:15
B:q
A:16
B:r
A:17
B:s
A:18
A:19
B:t
B:u
A:20
A:21
B:v
A:22
B:w
B:x
A:23
B:y
A:24
A:25
*/
Runnable操作
public class MainStartRunnable {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable() , "A");
Thread t2 = new Thread(new MyRunnable() , "B");
Thread t3 = new Thread(new MyRunnable() , "C");
t.start();
t2.start();
t3.start();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0 ; i < 10 ; i++) {
System.out.println(Thread.currentThread().getName()+" : "+i);
}
}
}
/*
B : 0
A : 0
A : 1
A : 2
A : 3
A : 4
A : 5
A : 6
A : 7
A : 8
A : 9
B : 1
B : 2
B : 3
B : 4
B : 5
B : 6
B : 7
B : 8
B : 9
C : 0
C : 1
C : 2
C : 3
C : 4
C : 5
C : 6
C : 7
C : 8
C : 9
*/
Callable操作
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class Demo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable callable = new MyCallable();
FutureTask<Integer> future = new FutureTask<>(callable);
new Thread(future).start();
System.out.println("线程返回 : "+future.get());
System.out.println("堵塞测试!!!");
}
static class MyCallable implements Callable<Integer>{
int num = 0;
//返回的方法
@Override
public Integer call() throws Exception {
for (int i = 1 ; i <= 100 ; i++) {
num += i;
System.out.println(Thread.currentThread().getName()+" : "+i);
}
return num;
}
}
}
/*
Thread-0 : 1
Thread-0 : 2
Thread-0 : 3
····
Thread-0 : 100
线程返回 : 5050
*/
synchronized安全线程
public class Demo {
public static void main(String[] args) {
Runnable t = new Ticket();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
static class Ticket implements Runnable{
private int count = 10;
private final Object o = new Object();
@Override
public void run() {
while (true){
synchronized (o){
if (count > 0){
//如果synchronized套在这里 , 多线程会错读
System.out.println(Thread.currentThread().getName()+" : "+ --count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}else {
break;
}
}
}
}
}
}
/*
Thread-2 : 9
Thread-2 : 8
Thread-2 : 7
Thread-0 : 6
Thread-1 : 5
Thread-0 : 4
Thread-2 : 3
Thread-0 : 2
Thread-1 : 1
Thread-0 : 0
堵塞测试!!!
*/
synchronized方法安全线程
public class Demo2 {
public static void main(String[] args) {
Runnable t = new Ticket();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}
static class Ticket implements Runnable{
int count = 10;
@Override
public void run() {
while (true){
if (sell()){
break;
}
}
}
private synchronized boolean sell() {
if (count > 0){
System.out.println(Thread.currentThread().getName()+" : "+ --count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
return true;
}
}
}
/*
Thread-0 : 9
Thread-0 : 8
Thread-0 : 7
Thread-0 : 6
Thread-0 : 5
Thread-0 : 4
Thread-3 : 3
Thread-3 : 2
Thread-1 : 1
Thread-1 : 0
* */
ReentrantLock安全线程
import java.util.concurrent.locks.ReentrantLock;
public class Demo3 {
public static void main(String[] args) {
Runnable lockTest = new LockTest();
new Thread(lockTest).start();
new Thread(lockTest).start();
new Thread(lockTest).start();
new Thread(lockTest).start();
}
static class LockTest implements Runnable{
//显式锁
static ReentrantLock l = new ReentrantLock(true);
int count = 10;
@Override
public void run() {
while (true){
l.lock();
if (sell()){
break;
}
if (count == 5){
test();
}
l.unlock();
}
l.unlock();
System.out.println("结束 : "+l.tryLock());
}
private void test() {
System.out.println(l.toString());
System.out.println(l.getHoldCount());
System.out.println(l.getQueueLength());
}
private boolean sell() {
if (count > 0){
System.out.println(Thread.currentThread().getName()+" : "+ --count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return false;
}
return true;
}
}
}
/*
Thread-0 : 9
Thread-3 : 8
Thread-2 : 7
Thread-1 : 6
Thread-0 : 5
java.util.concurrent.locks.ReentrantLock@47ee0a89[Locked by thread Thread-0]
1
3
Thread-3 : 4
Thread-2 : 3
Thread-1 : 2
Thread-0 : 1
Thread-3 : 0
结束 : true
结束 : false
*/
线程优先级
import javax.swing.*;
import java.awt.*;
public class PriorityBookTest extends JFrame {
private Container c = getContentPane();
private JProgressBar
jp1 = new JProgressBar(),
jp2 = new JProgressBar(),
jp3 = new JProgressBar(),
jp4 = new JProgressBar();
private Thread
threadA = null,
threadB = null,
threadC = null,
threadD = null;
public PriorityBookTest(){
super("线程优先级");
setBounds(300 , 230 ,100,150);
setLayout(new FlowLayout());
setVisible(true);
threadA = new Thread(newThread(c , jp1));
threadB = new Thread(newThread(c , jp2));
threadC = new Thread(newThread(c , jp3));
threadD = new Thread(newThread(c , jp4));
setPriority("A" , 10 , threadA);
setPriority("B" , 7 , threadB);
setPriority("C" , 4 , threadC);
setPriority("D" , 1 , threadD);
}
private static Thread newThread(Container c , JProgressBar jp){
c.add(jp);
jp.setStringPainted(true);
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int count = 0 ;
while (count <= 100){
jp.setValue(count++);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
return thread;
}
public static void setPriority(String threadName , int priority , Thread t){
//设置进程优先级、名,启动
t.setPriority(priority);
t.setName(threadName);
t.start();
}
public static void main(String[] args) {
new PriorityBookTest();
}
}
/*
执行结果 : 窗体展示 进度条
*/
缓存线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//缓存线程池
public class Demo1 {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
//执行任务
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 1");
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 2");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 4");
}
});
}
}
/*
pool-1-thread-3 : 3
pool-1-thread-2 : 2
pool-1-thread-1 : 1
pool-1-thread-1 : 4
*/
定长线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//定长线程池
public class Demo2 {
public static void main(String[] args) {
ExecutorService exception = Executors.newFixedThreadPool(2);
exception.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 1");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
exception.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 2");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
exception.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 3");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
exception.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 4");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
/*
pool-1-thread-1 : 1
pool-1-thread-2 : 2
pool-1-thread-2 : 3
pool-1-thread-1 : 4
*/
单线程线程池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//单线程线程池
public class Demo3 {
public static void main(String[] args) {
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
service.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" : 3");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
/*
pool-1-thread-1 : 1
pool-1-thread-1 : 2
pool-1-thread-1 : 3
*/
周期性任务定长线程池
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
//周期性任务定长线程池
public class Demo4 {
public static void main(String[] args) {
ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
/**定时执行
* 参数1. 线程
* 参数2. 延时时长值
* 参数3. 时长单位
*/
service.schedule(new Runnable() {
@Override
public void run() {
System.out.println("延时2s , 执行的程序");
}
} , 2 , TimeUnit.SECONDS);
/**周期执行
* 参数1. 线程
* 参数2. 延时时长值
* 参数3. 周期间隔时长值
* 参数4. 时长单位
*/
service.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("延时3s 执行周期间隔2s 的循环程序");
}
} , 3 , 2 , TimeUnit.SECONDS);
}
}
/*
延时2s , 执行的程序
延时3s 执行周期间隔2s 的循环程序
延时3s 执行周期间隔2s 的循环程序
延时3s 执行周期间隔2s 的循环程序
·····
*/