
進(jìn)階線程啦~.png
進(jìn)程
是了解線程之前的首要概念,當(dāng)我們想要在系統(tǒng)中運(yùn)行程序,首先需要向操作系統(tǒng)申請資源(內(nèi)存、文件句柄),申請資源在操作系統(tǒng)中的基本單位是進(jìn)程。一個進(jìn)程可以包含多個線程,同一個進(jìn)程中的線程共享該進(jìn)程中的資源,如內(nèi)存空間、文件句柄等
HelloThread
線程創(chuàng)建、啟動、運(yùn)行
新建線程 new
啟動線程 start
運(yùn)行線程 run -- 運(yùn)行一個線程就是讓JVM執(zhí)行該線程的 run 方法
public class HelloThread {
public static void main(String[] args) {
Thread thread = new Thread();
Thread childThread = new ChildThread();
Thread childThred2 = new Thread(new ChildThread());
Thread student = new Thread(new StudentRunnable());
System.out.println("----------- Test thread's name in Called Method -----------");
threadName();
System.out.println("----------- Test 1. new Thread() 2.setName(\"HelloWorld\") -----------");
thread.setName("HelloWorld");
thread.start();
System.out.println("Thread: " + thread.getName() + " starting");
System.out.println("----------- Test ChildThread -----------");
childThread.start();
System.out.println("ChildThread: " + childThread.getName() + " starting...");
childThred2.start();
// 線程是“一次性用品”
// 多次調(diào)用同一 thread 的 start 會出現(xiàn) IllegalThreadStateException
// 因為threadStatus != 0 0為線程初始狀態(tài)
// childThred2.start();
System.out.println("ChildThread: " + childThred2.getName() + " starting...");
System.out.println("----------- Test Student of Runnable -----------");
student.start();
System.out.println("StudentThread: " + student.getName() + " starting...");
}
public static void threadName() {
System.out.println("The thread name of main called method's currentThread is " + Thread
.currentThread().getName());
}
}
class ChildThread extends Thread {
@Override
public void run() {
// 執(zhí)行run的順序是不一定的
// run執(zhí)行完畢,線程即結(jié)束
// 結(jié)束后,所占用的資源包括內(nèi)存都將被JVM回收
System.out.println(Thread.currentThread().getName() + " running...");
}
}
class StudentRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " running...");
}
}
Console Output:
----------- Test thread's name in Called Method -----------
The thread name of main called method's currentThread is main
----------- Test 1. new Thread() 2.setName("HelloWorld") -----------
Thread: HelloWorld starting
----------- Test ChildThread -----------
ChildThread: Thread-1 starting...
ChildThread: Thread-3 starting...
----------- Test Student of Runnable -----------
----------- Test run of ChildThread -----------
Thread-3 running...
----------- Test run of ChildThread -----------
Thread-1 running...
Thread-4 running...
StudentThread: Thread-4 starting...
- Thread的創(chuàng)建默認(rèn)下標(biāo)從0開始,如源碼示 threadInitNumber for 匿名線程自增長編號。threadInitNumber 初始為0
/* For autonumbering anonymous threads. */
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
創(chuàng)建線程綜述:
@Override
public void run() {
if (target != null) {
target.run();
}
}
基于Thread的run實現(xiàn)(實現(xiàn)Runnable的run),創(chuàng)建線程有兩種方式:
1. 基于繼承(Inheritance)。實現(xiàn) Thread 中的 run 方法
2. 基于組合(Composition)。new Thread(Ruannable instance) 通過 Runnable 的實例,執(zhí)行實例中的 run。實用組合更好的降低耦合
public class ThreadCreation {
private static final String PREFIX = "prefix";
public static void main(String[] args) {
// ---------- 獲取處理器個數(shù) ----------
final int processorNum = Runtime.getRuntime().availableProcessors();
// ---------- 創(chuàng)建線程方式 ----------
// ---------- 創(chuàng)建線程.Way1 基于繼承 ----------
ChildrenOfRunnable runnableTask = new ChildrenOfRunnable();
IntStream.range(0, 2 * processorNum).mapToObj(index -> new Thread(runnableTask)).forEach(
Thread::start);
// ---------- 創(chuàng)建線程.Way2 基于組合 ----------
Thread thread = new ChildrenOfThread();
thread.start();
}
@Override
public void run() {
System.out.println("childrenOfThread is running.");
}
}
static class ChildrenOfRunnable implements Runnable {
private int index = 0;
@Override
public void run() {
static class ChildrenOfThread extends Thread {
System.out.println("childrenOfRunnable " + index++ + " is running.");
}
}
}
線程核心屬性
-
id同一個JVM實例中不會存在重復(fù)的線程id,默認(rèn)從0開始自增 -
name主要便于開發(fā)人員查看,是可以重復(fù)的 -
daemon是否要設(shè)置為守護(hù)線程,默認(rèn)同父線程daemon性質(zhì)一致。守護(hù)線程一般執(zhí)行一些重要性不是很高的任務(wù),比如監(jiān)聽其他線程的運(yùn)行情況 -
priority線程優(yōu)先級,默認(rèn)同父線程priority值一致,1≤n≤線程組priority≤10。優(yōu)先級并一定保證線程會按照優(yōu)先級的順序執(zhí)行,只是給到調(diào)度器一個提示信息。
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
線程屬性設(shè)置主要在Thread.init:
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter use the parent thread group. */
if (g == null) {
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is explicitly passed in. */
g.checkAccess();
/* Do we have the required permissions? */
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;
setPriority(priority);
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* Set thread ID */
tid = nextThreadID();
}
線程常用方法
-
synchronized void start()啟動線程。一個線程被start多次會拋出-IllegalThreadStateException異常 -
void run()實現(xiàn)線程的任務(wù)處理邏輯。一般,程序不應(yīng)該直接調(diào)用該方法,由JVM調(diào)用 -
final synchronized void join()等待相應(yīng)線程運(yùn)行結(jié)束。T_A調(diào)用T_B的join(),T_A將會等待T_B執(zhí)行結(jié)束再執(zhí)行 -
static void yield()主動放棄對當(dāng)前時間片的占用,但是方法的執(zhí)行并不可靠。若T_A調(diào)用yield方法:- 當(dāng)前資源空閑,調(diào)度器會忽略這個提示,T_A繼續(xù)執(zhí)行
- 當(dāng)前資源忙,T_A主動放棄當(dāng)前時間片,調(diào)度器收到提示切換上下文,T_A掛起
-
static void sleep()一定會執(zhí)行,掛起一定時間 -
static Thread currentThread()返回執(zhí)行當(dāng)前代碼的線程 -
void interrupt()主動打斷線程阻塞狀態(tài) -
boolean isInterrupted()執(zhí)行isInterrupted(false)返回 if this thread has been interrupted; 即線程是否被打斷過 -
static boolean interrupted()實際上執(zhí)行currentThread().isInterrupted(true);即返回當(dāng)前線程的interrupted并復(fù)位interrupted狀態(tài) -
native boolean isInterrupted(boolean ClearInterrupted)線程是否被打斷,同時是否復(fù)位interrupted標(biāo)識