创建和运行线程
mport lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
/**
* @Author blackcat
* @version: 1.0
* @description:线程创建
*/
@Slf4j
public class ThreadCreate {
public static void main(String[] args) throws ExecutionException, InterruptedException {
//1、直接使用 Thread
Thread thread = new Thread("thread") {
@Override
public void run() {
log.info("thread hello");
}
};
thread.start();
//2、使用 Runnable 配合 Thread
// Java 8 以后可以使用 lambda 精简代码 Runnable target = () -> log.info("runnable hello");
Runnable target = new Runnable() {
@Override
public void run() {
log.info("runnable hello");
}
};
Thread runThread = new Thread(target, "runnable");
runThread.start();
//3、FutureTask 配合 Thread 有返回值
FutureTask<Integer> task = new FutureTask<>(() -> {
log.debug(" futureTask hello");
int i = 100 / 0;
return 100;
});
new Thread(task, "futureTask").start();
try {
//阻塞等待
Integer number = task.get();
log.info("task result :[{}]", number);
} catch (Exception e) {
e.printStackTrace();
}
}
}
常见API
| 方法名 | static | 功能说明 | 注意 |
|---|---|---|---|
| start() | 启动一个新线程,在新的线程运行run方法中的代码 | start方法只是让线程静茹就绪,里面代码不一定立刻运行(CPU时间片还没分给它).每个线程对象start方法只能调用一次,调用多次会出现illegalThreadStateException | |
| run() | 新线程启动会调用的方法 | 如果在构造Thread对象中传递了Runnable参数,则会调用默认的run方法.如果通过创建Thread的子类对象,会覆盖默认方法 | |
| join() | 等待线程运行结束 | ||
| join(long n) | 等待线程运行结束,最多等n毫秒 | ||
| getId() | 获取线程id | id唯一 | |
| getName() | 获取线程名 | ||
| serName(String) | 设置线程名 | ||
| getPriority() | 获取线程优先级 | ||
| setPriority(int) | 设置线程优先级 | ||
| getStatus() | 获取线程状态 | java中线程状态有6种:NEW,RUNNABLE,BLOCKED WAITING,TIMED_WAITING,TERMINATED | |
| isInterrupted() | 判断是否被打断 | 不会清除打断标记 | |
| isAlive() | 线程是否存活 | ||
| interrupt() | 打断线程 | 如果被打断线程正在 sleep,wait,join 会导致被打断的线程抛出 InterruptedException,并清除打断标记 ;如果打断的正在运行的线程(或park),则会设置打断标记 ; | |
| interrupted() | static | 判断是否被打断 | 会清除打断标记 |
| currentThread() | static | 获取当前正在执行的线程 | |
| sleep(long n) | static | 让当前执行的线程休眠n毫秒,休眠时让出cpu的时间片给其他的线程 | |
| yield() | static | 提示线程调度器 | 用于测试和调试 |
| stop() | 停止线程运行 | 过时 | |
| suspend() | 挂起(暂停)线程运行 | 过时 | |
| resume() | 恢复线程运行 | 过时 |
start() 和 run()
import lombok.extern.slf4j.Slf4j;
/**
* @Author blackcat
* @version: 1.0
* @description:Thread 的run()和start()的方法 (start()多次调用会报IllegalThreadStateException)
*/
@Slf4j
public class ThreadStartAndRun {
public static void main(String[] args) {
Thread thread = new Thread(() -> {
log.debug("running");
},"启动线程");
//主线程调用方法
thread.run();
log.debug("thread before: [{}]' ",thread.getState());
//启动线程 得到CPU时间片后 会调用run()
thread.start();
log.debug("thread after:[{}]",thread.getState());
thread.start();
}
}
sleep() and yield()
sleep
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
/**
* @Author blackcat
* @version: 1.0
* @description: sleep:
* 1. 调用 sleep 会让当前线程从 Running 进入 Timed Waiting 状态(阻塞)
* 2. 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException(打断标记会清空)
* 3. 睡眠结束后的线程未必会立刻得到执行
* 4. 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性(JDK1.5以后)
* <p>
* <p>
* sleep的应用:
* 在没有利用 cpu 来计算时,不要让 while(true) 空转浪费 cpu,这时可以使用 yield 或
* sleep 来让出 cpu 的使用权给其他程序.适用于无锁状态
* while(true) {
* try {
* Thread.sleep(50);
* } catch (InterruptedException e) {
* e.printStackTrace();
* }
* }
*
*/
@Slf4j
public class ThreadSleep {
public static void main(String[] agrs){
Thread t1 = new Thread("t1") {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(2);
//Thread.sleep(2000);
} catch (InterruptedException e) {
log.info("interrupted");
e.printStackTrace();
}
}
};
t1.start();
log.info("t1 state: [{}]", t1.getState());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("t1 state: [{}]", t1.getState());
t1.interrupt();
}
}
yield
-
调用 yield 会让当前线程从 Running 进入 Runnable 就绪状态,然后调度执行其它线程
-
具体的实现依赖于操作系统的任务调度器
setPriority
/**
* @Author blackcat
* @version: 1.0
* @description:
* 线程优先级
* 1.线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它
* 2.如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但cpu闲时,优先级几乎没作用
*
*/
public class ThreadPriority {
public static void main(String[] args) {
Runnable task1 = () -> {
int count = 0;
for (;;) {
System.out.println("---->1 " + count++);
}
};
Runnable task2 = () -> {
int count = 0;
for (;;) {
//理论上线程1打印多
// Thread.yield();
System.out.println(" ---->2 " + count++);
}
};
Thread t1 = new Thread(task1, "t1");
Thread t2 = new Thread(task2, "t2");
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.MAX_PRIORITY);
t1.start();
t2.start();
}
}
join() and join(long n)
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.TimeUnit;
/**
* @Author blackcat
* @version: 1.0
* @description:join 等待线程结束
*/
@Slf4j
public class ThreadJoin {
static int r = 0;
static int r2 = 0;
public static void main(String[] args) throws InterruptedException {
join();
join2();
join3();
}
private static void join() throws InterruptedException {
log.debug("开始");
Thread t1 = new Thread(() -> {
log.debug("开始");
sleep(1);
log.debug("结束");
r = 10;
});
t1.start();
t1.join();
log.debug("结果为:[{}]", r);
log.debug("结束");
}
private static void join2() throws InterruptedException {
Thread t1 = new Thread(() -> {
sleep(1);
r = 10;
});
Thread t2 = new Thread(() -> {
sleep(2);
r2 = 20;
});
long start = System.currentTimeMillis();
t1.start();
t2.start();
t1.join();
t2.join();
long end = System.currentTimeMillis();
log.debug("r1: {} r2: {} cost: {}", r, r2, end - start);
}
private static void join3() throws InterruptedException {
Thread t1 = new Thread(() -> {
sleep(2);
r = 10;
});
long start = System.currentTimeMillis();
t1.start();
// 线程执行结束或是等待时间到了 join 结束
// t1.join(3000);
t1.join(1500);
long end = System.currentTimeMillis();
log.debug("r:{} cost: {}", r,end - start);
}
private static void sleep(int i) {
try {
TimeUnit.SECONDS.sleep(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
interrupt
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.locks.LockSupport;
/**
* @Author blackcat
* @create 2021/7/19 21:23
* @version: 1.0
* @description:线程打断方法 如果被打断线程正在 sleep,wait,join 会导致被打断的线程抛出InterruptedException,并清除打断标记;
* 如果打断的正在运行的线程(或park),则会设置打断标记;
*/
@Slf4j
public class ThreadInterrupt {
public static void main(String[] agrs) throws InterruptedException {
interruptWait();
interrupt();
interruptPark();
}
private static void interruptPark() throws InterruptedException {
Thread t3 = new Thread(() -> {
log.info("park...");
//当打断标记为true时 park阻塞无效
LockSupport.park();
log.info("unpark...");
// log.debug("park 打断后:{}",Thread.interrupted());
log.debug("park 打断后:{}", Thread.currentThread().isInterrupted());
log.info("again park...");
LockSupport.park();
log.info("again unpark...");
}, "t3");
t3.start();
Thread.sleep(200);
t3.interrupt();
}
//打断正常的方法
private static void interrupt() throws InterruptedException {
Thread t2 = new Thread(() -> {
while (true) {
Thread current = Thread.currentThread();
boolean interrupted = current.isInterrupted();
//打断标记,线程自己判断
if (interrupted) {
log.info(" 打断状态: {}", interrupted);
break;
}
}
}, "t2");
t2.start();
Thread.sleep(1000);
t2.interrupt();
}
//打断阻塞状态(sleep\wait\join)
private static void interruptWait() throws InterruptedException {
Thread t1 = new Thread("t1") {
@Override
public void run() {
log.info("sleep");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
log.info("interrupted");
e.printStackTrace();
}
}
};
t1.start();
Thread.sleep(1000);
t1.interrupt();
//打断阻塞状态会重置打断标记
log.info("interrupt status:{}", t1.isInterrupted());
}
}
关闭线程(两阶段终止模式)
/**
* @Author blackcat
* @version: 1.0
* @description:
*
* Two Phase Termination(两阶段终止模式)
* 在一个线程 T1 中如何“优雅”终止线程 T2?这里的【优雅】指的是给 T2 一个料理后事的机会。
*/
@Slf4j
public class TPTInterrupt {
private Thread thread;
public void start(){
thread = new Thread(() -> {
while(true){
Thread currentThread = Thread.currentThread();
boolean interrupted = currentThread.isInterrupted();
if(interrupted){
log.info("料理后事,停止线程");
break;
}
try {
Thread.sleep(2000);
log.info("执行监控记录");
} catch (InterruptedException e) {
currentThread.interrupt();
e.printStackTrace();
}
}
},"监控线程");
thread.start();
}
public void stop() {
log.info("打断");
thread.interrupt();
}
public static void main(String[] agrs) throws InterruptedException {
TPTInterrupt t = new TPTInterrupt();
t.start();
Thread.sleep(3500);
t.stop();
}
}
/**
* @Author blackcat
* @version: 1.0
* @description: 保证只启动一个监控线程
*/
@Slf4j
public class TPTInterrupt {
private Thread thread;
private volatile boolean started = false;
public synchronized void start() {
if (started) {
return;
}
started = true;
thread = new Thread(() -> {
while (true) {
Thread currentThread = Thread.currentThread();
boolean interrupted = currentThread.isInterrupted();
if (interrupted) {
log.info("料理后事,停止线程");
break;
}
try {
Thread.sleep(2000);
log.info("执行监控记录");
} catch (InterruptedException e) {
currentThread.interrupt();
e.printStackTrace();
}
}
}, "监控线程");
thread.start();
}
public synchronized void stop() {
log.info("打断");
started = false;
thread.interrupt();
}
public static void main(String[] agrs) throws InterruptedException {
TPTInterrupt t = new TPTInterrupt();
t.start();
t.start();
Thread.sleep(3500);
t.stop();
}
}
守护线程
import lombok.extern.slf4j.Slf4j;
/**
* @Author blackcat
* @create 2021/7/20 14:20
* @version: 1.0
* @description:
*
* 守护线程,只要其它非守护线程运行结束了,即使守护线程的代码没有执行完,也会强制结束。
*/
@Slf4j
public class ThreadDaemon {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
while (true) {
if (Thread.currentThread().isInterrupted()) {
break;
}
}
log.info("t1结束");
}, "t1");
//启动当主线程结束 当前线程也会强制结束
// t1.setDaemon(true);
t1.start();
Thread.sleep(1000);
log.info("main 结束");
}
}
线程状态
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
/**
* @Author blackcat
* @version: 1.0
* @description:线程的六种状态
*/
@Slf4j
public class ThreadState {
public static void main(String[] args) throws IOException {
Thread t1 = new Thread("t1") {
@Override
public void run() {
log.info("running...");
}
};
Thread t2 = new Thread("t2") {
@Override
public void run() {
while(true) { // runnable
}
}
};
t2.start();
Thread t3 = new Thread("t3") {
@Override
public void run() {
log.info("running...");
}
};
t3.start();
Thread t4 = new Thread("t4") {
@Override
public void run() {
synchronized (ThreadState.class) {
try {
Thread.sleep(1000000); // timed_waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t4.start();
Thread t5 = new Thread("t5") {
@Override
public void run() {
try {
t2.join(); // waiting
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t5.start();
Thread t6 = new Thread("t6") {
@Override
public void run() {
synchronized (ThreadState.class) { // blocked
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t6.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
//NEW
log.info("t1 state {}", t1.getState());
//RUNNABLE
log.info("t2 state {}", t2.getState());
//TERMINATED
log.info("t3 state {}", t3.getState());
//TIMED_WAITING/BLOCKED
log.info("t4 state {}", t4.getState());
//WAITING
log.info("t5 state {}", t5.getState());
//BLOCKED/TIMED_WAITING
log.info("t6 state {}", t6.getState());
}
}