1. 继承 Thread 类
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread run");
}
}
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
2. 实现 Runnable 接口
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("MyRunnable run");
}
}
public class Test {
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
}
}
3. currentThread() 方法
currentThread() 方法可以返回代码段正在被哪个线程调用的信息
public class MyThread extends Thread {
public MyThread() {
System.out.println("构造方法打印:" + Thread.currentThread().getName());
}
@Override
public void run() {
System.out.println("run 方法打印:" + Thread.currentThread().getName());
}
}
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}
}
4. isAlive() 方法
isAlive() 方法判断当前线程是否处于活动状态
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("run isAlive= " + this.isAlive());
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
System.out.println("before isAlive=" + myThread.isAlive());
myThread.start();
// Thread.sleep(1000);
System.out.println("after isAlive=" + myThread.isAlive());
}
}
5. sleep() 方法
sleep() 方法在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。“正在执行的线程”是指 this.currentThread() 返回的线程
public class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("run begin threadName=" + this.getName() + " time=" + System.currentTimeMillis());
Thread.sleep(2000);
System.out.println("run end threadName=" + this.getName() + " time=" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
System.out.println("begin time=" + System.currentTimeMillis());
myThread.start();
System.out.println("end time=" + System.currentTimeMillis());
}
}
6. getId() 方法
getId() 方法可以取得线程的唯一标识
public class Test {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName() + " " + Thread.currentThread().getId());
}
}
7. 停止线程
7.1 interrupt() 方法
interrupt() 方法无法马上中断线程,仅仅是对线程打了一个中断的标记,不是真正的中断线程
public class MyThread extends Thread {
@Override
public void run() {
for (int i = 0;i < 500000;i++) {
System.out.println("i=" + i);
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(500);
myThread.interrupt();
}
}
7.2 判断线程是否中断状态
-
interrupted()方法判断当前线程是否是中断状态,如果是则清除中断状态public class Test { public static void main(String[] args) { Thread.currentThread().interrupt(); System.out.println("是否停止1 " + Thread.interrupted()); System.out.println("是否停止2 " + Thread.interrupted()); System.out.println("end"); } } -
isInterrupted()方法判断指定线程是否是中断状态,不清除中断状态public class MyThread extends Thread { @Override public void run() { for (int i = 0;i < 500000;i++) { System.out.println("i=" + i); } } } public class Test { public static void main(String[] args) throws InterruptedException { MyThread myThread = new MyThread(); myThread.start(); Thread.sleep(500); myThread.interrupt(); System.out.println("是否停止1 " + myThread.isInterrupted()); System.out.println("是否停止2 " + myThread.isInterrupted()); System.out.println("end"); } }
7.3 停止线程-异常法(建议)
public class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0;i < 500000;i++) {
if (this.isInterrupted()) {
System.out.println("中断状态,退出");
throw new InterruptedException();
}
System.out.println("i=" + i);
}
System.out.println("for 循环下面");
} catch (InterruptedException e) {
System.out.println("MyThread catch");
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) {
try {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(500);
myThread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("main end");
}
}
7.4 停止线程-沉睡法
-
先休眠后中断
public class MyThread extends Thread { @Override public void run() { try { System.out.println("run begin"); Thread.sleep(20000); System.out.println("run end"); } catch (InterruptedException e) { System.out.println("MyThread catch isInterrupted=" + this.isInterrupted()); e.printStackTrace(); } } } public class Test { public static void main(String[] args) throws InterruptedException { MyThread myThread = new MyThread(); myThread.start(); Thread.sleep(2000); myThread.interrupt(); } } -
先中断后休眠
public class MyThread extends Thread { @Override public void run() { try { System.out.println("run begin"); for (int i = 0;i < 500000;i++) { System.out.println("i=" + i); if (i == 400000) { Thread.sleep(100); } } System.out.println("run end"); } catch (InterruptedException e) { System.out.println("MyThread catch"); e.printStackTrace(); } } } public class Test { public static void main(String[] args) throws InterruptedException { MyThread myThread = new MyThread(); myThread.start(); myThread.interrupt(); } }
7.5 停止线程-暴力法(不建议)
-
stop()方法可以暴力停止线程public class MyThread extends Thread { @Override public void run() { try { int i = 0; while (true) { System.out.println("i=" + (i++)); Thread.sleep(100); } } catch (InterruptedException e) { e.printStackTrace(); } } } public class Test { public static void main(String[] args) throws InterruptedException { MyThread myThread = new MyThread(); myThread.start(); Thread.sleep(2000); myThread.stop(); } } -
stop()方法已经被废弃。如果让线程强制停止可能会使一些清理性的工作得不到完成;还可能对锁对象进行了“解锁”,导致数据得不到同步处理,出现数据不一致问题public class Service { private String username = "a"; private String password = "aaa"; public String getUsername() { return username; } public String getPassword() { return password; } synchronized public void login(String username, String password) { try { this.username = username; Thread.sleep(20000); this.password = password; } catch (InterruptedException e) { e.printStackTrace(); } } } public class MyThread extends Thread { private Service service; public MyThread(Service service) { this.service = service; } @Override public void run() { service.login("b", "bbb"); } } public class Test { public static void main(String[] args) throws InterruptedException { Service service = new Service(); MyThread myThread = new MyThread(service); myThread.start(); Thread.sleep(2000); myThread.stop(); System.out.println("username=" + service.getUsername() + " password=" + service.getPassword()); } }
7.6 停止线程-返回法
public class MyThread extends Thread {
@Override
public void run() {
int i = 0;
while (true) {
if (this.isInterrupted()) {
System.out.println("停止了,退出");
return;
}
System.out.println("i=" + (i++));
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(3000);
myThread.interrupt();
}
}
8. 暂停线程(不建议)
8.1 suspend() 和 resume() 方法的使用
public class MyThread extends Thread {
private long i;
public long getI() {
return i;
}
@Override
public void run() {
while (true) {
i++;
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(3000);
myThread.suspend();
System.out.println("suspend 1-1 time=" + System.currentTimeMillis() + " i=" + myThread.getI());
Thread.sleep(3000);
System.out.println("suspend 1-2 time=" + System.currentTimeMillis() + " i=" + myThread.getI());
myThread.resume();
Thread.sleep(3000);
myThread.suspend();
System.out.println("suspend 2-1 time=" + System.currentTimeMillis() + " i=" + myThread.getI());
Thread.sleep(3000);
System.out.println("suspend 2-2 time=" + System.currentTimeMillis() + " i=" + myThread.getI());
}
}
8.2 suspend() 和 resume() 方法的缺点-独占
-
case1:
public class Service { synchronized public void testA() { System.out.println(Thread.currentThread().getName() + " begin"); if (Thread.currentThread().getName().equals("a")) { System.out.println(Thread.currentThread().getName() + " suspend"); Thread.currentThread().suspend(); } System.out.println(Thread.currentThread().getName() + " end"); } } public class Test { public static void main(String[] args) throws InterruptedException { final Service service = new Service(); Thread a = new Thread() { @Override public void run() { service.testA(); } }; a.setName("a"); a.start(); Thread.sleep(1000); Thread b = new Thread() { @Override public void run() { service.testA(); } }; b.setName("b"); b.start(); } } -
case2:
System.out.println()方法是synchronized同步块打印字符串,suspend()导致synchronized持有的锁对象无法释放,所以案例中"main end"无法打印public class MyThread extends Thread { @Override public void run() { int i = 0; while (true) { i++; System.out.println(i); } } } public class Test { public static void main(String[] args) throws InterruptedException { MyThread myThread = new MyThread(); myThread.start(); Thread.sleep(3000); myThread.suspend(); System.out.println("main end"); } }
8.3 suspend() 和 resume() 方法的缺点-不同步
public class Service {
private String username = "a";
private String password = "aaa";
public void setValue(String username, String password) {
this.username = username;
if (Thread.currentThread().getName().equals("a")) {
System.out.println(Thread.currentThread().getName() + " suspend");
Thread.currentThread().suspend();
}
this.password = password;
}
public void getValue() {
System.out.println(username + " " + password);
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
final Service service = new Service();
Thread a = new Thread(new Runnable() {
@Override
public void run() {
service.setValue("b", "bbb");
}
});
a.setName("a");
a.start();
Thread.sleep(2000);
service.getValue();
}
}
9. yield() 方法
yield() 方法是当前线程放弃 CPU 资源给其他线程使用,但是放弃时间不确定,可能放弃后有马上获得资源
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
int count = 0;
for (int i = 0;i < 5000000;i++) {
// Thread.yield();
count = count + (i + 1);
}
long endTime = System.currentTimeMillis();
System.out.println("耗时:" + (endTime - beginTime) + "毫秒");
}
});
thread.start();
}
}
10. 线程的优先级
10.1 线程优先级的继承特性
线程的优先级具有继承性,比如 A 线程启动 B 线程,则 A 和 B 两个线程的优先级是一样的
public class ThreadA extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " priority=" + this.getPriority());
ThreadB b = new ThreadB();
b.start();
}
}
public class ThreadB extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " priority=" + this.getPriority());
}
}
public class Test {
public static void main(String[] args) {
ThreadA a = new ThreadA();
a.setPriority(8);
a.start();
}
}
10.2 setPriority() 方法
setPriority() 方法可以设置线程的优先级(1-10)。高优先级的线程总是大部分先执行完,但不代表高优先级的线程全部先执行完成
public class ThreadA extends Thread {
@Override
public void run() {
for (int i = 0;i < 500000;i++) {
System.out.println(Thread.currentThread().getName() + " *****");
}
}
}
public class ThreadB extends Thread {
@Override
public void run() {
for (int i = 0;i < 500000;i++) {
System.out.println(Thread.currentThread().getName() + " ------");
}
}
}
public class Test {
public static void main(String[] args) {
ThreadA a = new ThreadA();
a.setName("ThreadA");
a.setPriority(1);
ThreadB b = new ThreadB();
b.setName("ThreadB");
b.setPriority(10);
a.start();
b.start();
}
}
11. 守护线程
Java 线程有两种:用户线程和守护线程。当进程中不存在用户线程了,则守护线程自动销毁。典型的守护线程例子是垃圾回收线程
public class MyThread extends Thread {
@Override
public void run() {
try {
int i = 0;
while (true) {
System.out.println(Thread.currentThread().getName() + " i=" + (i++));
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.setDaemon(true);
myThread.start();
Thread.sleep(2000);
System.out.println("main end");
}
}
学自《Java多线程编程核心技术》