线程,是进程下面的一个单位,一个进程可以由很多个线程组成。为了提高CPU的使用率,Java提供了多线程编程。今天,就让我们来学习一下Java里面多线程最基础的一个类Thread。
1.线程的状态: NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED。
2.每个Thread都有一个优先级priority,优先级高的线程优先执行。优先级的大小可通过setPriority(int newPriority)设置,范围是 [1,10],超过该范围会抛出IllegalArgumentException。
3.Java线程分为用户线程和守护线程,它们的区别在于:主线程结束后,用户线程依旧会执行,JVM处于存活状态;主线程结束后,如果没有用户线程(全都是守护线程),那么守护线程结束,JVM关闭。守护线程也称为服务线程,主要是为了给用户线程提供服务,在没有用户线程可服务时会自动消亡。Thread可以通过setDaemon(boolean on)设置。
4.eg:用户线程,JVM启动调用main函数的线程。守护线程,GC线程。
5.新创建的线程的优先级跟父线程一致,是否是守护线程也跟父线程一致。
//thread构造方法
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
...
//得到父线程
Thread parent = currentThread();
...
//设置子线程daemon和priority为父线程的值
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
setPriority(priority);
}
6.Java虚拟机会持续运行Java线程,直到下面任何一种情况发生:
7.start()方法,用于启动线程。线程启动后,Java虚拟机就会执行线程的run方法。注意,任何线程都不能重复启动,否则会报IllegalThreadStateException。
8.线程中断。Java的线程中断实际上只是修改线程的中断标志,线程真正停止需要线程自己控制。
8.4.线程中断的方法:
import java.util.concurrent.TimeUnit;
public class TestThreadInterrupt {
public static void main(String[] args) {
Thread thread = new Thread(new WorkerThread());
thread.start();
try {
TimeUnit.SECONDS.sleep(6l);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}
class WorkerThread implements Runnable {
@Override
public void run() {
while (true) {
// 中断状态判断
if (Thread.currentThread().isInterrupted()) {
break;
}
System.out.println("do work");
try {
TimeUnit.SECONDS.sleep(3l);
} catch (InterruptedException e) {
System.out.println("I was interrupted");
// 由于sleep方法中断的时候会清除中断标志,所以需要重设中断标志
Thread.currentThread().interrupt();
}
}
}
}
9.yield(),线程让步。当一个线程使用了yield()方法后,它会让出CPU执行时间,让自己或者其他线程运行。注意,此处是让自己或其他线程运行,并不是单纯的让给其他线程。另外,优先级高的线程会优先执行。
public class TestThreadYield {
public static void main(String[] args) {
Thread thread0 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
//thread0让出CPU
Thread.yield();
System.out.println(Thread.currentThread().getName());
}
}
}, "thread0");
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}, "thread1");
thread0.start();
//CPU设为最大优先级
thread1.setPriority(Thread.MAX_PRIORITY);
thread1.start();
}
}
10.join(long millis)。等待最多millis毫秒直到该线程结束。millis为0表示一直等待直到该线程结束。
package com.code.thread;
public class TestThreadJoin {
public static void main(String[] args) {
Thread thread0 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}, "thread0");
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName());
}
}
}, "thread1");
thread0.start();
try {
//等待线程thread0直到结束
//注意join方法必须在start后面
thread0.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
thread1.start();
}
}
11.线程顺序执行的方法
package com.code.thread;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadInTurn {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Runnable a = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Runnable a");
}
}
};
Runnable b = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Runnable b");
}
}
};
executor.execute(a);
executor.execute(b);
executor.shutdown();
}
}
12.线程变量ThreadLocal,它是跟线程绑定的变量。如果我们需要定义跟线程相关的变量,那么我们可以使用ThreadLocal。