进程
是了解线程之前的首要概念,当我们想要在系统中运行程序,首先需要向操作系统申请资源(内存、文件句柄),申请资源在操作系统中的基本单位是进程。一个进程可以包含多个线程,同一个进程中的线程共享该进程中的资源,如内存空间、文件句柄等
HelloThread
线程创建、启动、运行
新建线程 new
启动线程 start
运行线程 run -- 运行一个线程就是让JVM执行该线程的 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();
// 线程是“一次性用品”
// 多次调用同一 thread 的 start 会出现 IllegalThreadStateException
// 因为threadStatus != 0 0为线程初始状态
// 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() {
// 执行run的顺序是不一定的
// run执行完毕,线程即结束
// 结束后,所占用的资源包括内存都将被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的创建默认下标从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);
}
创建线程综述:
@Override
public void run() {
if (target != null) {
target.run();
}
}
基于Thread的run实现(实现Runnable的run),创建线程有两种方式:
1. 基于继承(Inheritance)。实现 Thread 中的 run 方法
2. 基于组合(Composition)。new Thread(Ruannable instance) 通过 Runnable 的实例,执行实例中的 run。实用组合更好的降低耦合
public class ThreadCreation {
private static final String PREFIX = "prefix";
public static void main(String[] args) {
// ---------- 获取处理器个数 ----------
final int processorNum = Runtime.getRuntime().availableProcessors();
// ---------- 创建线程方式 ----------
// ---------- 创建线程.Way1 基于继承 ----------
ChildrenOfRunnable runnableTask = new ChildrenOfRunnable();
IntStream.range(0, 2 * processorNum).mapToObj(index -> new Thread(runnableTask)).forEach(
Thread::start);
// ---------- 创建线程.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实例中不会存在重复的线程id,默认从0开始自增 -
name
主要便于开发人员查看,是可以重复的 -
daemon
是否要设置为守护线程,默认同父线程daemon性质一致。守护线程一般执行一些重要性不是很高的任务,比如监听其他线程的运行情况 -
priority
线程优先级,默认同父线程priority值一致,1≤n≤线程组priority≤10
。优先级并一定保证线程会按照优先级的顺序执行,只是给到调度器一个提示信息。
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
线程属性设置主要在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()
实现线程的任务处理逻辑。一般,程序不应该直接调用该方法,由JVM调用 -
final synchronized void join()
等待相应线程运行结束。T_A
调用T_B
的join()
,T_A
将会等待T_B执行结束
再执行 -
static void yield()
主动放弃对当前时间片的占用,但是方法的执行并不可靠
。若T_A调用yield方法:- 当前资源空闲,调度器会忽略这个提示,T_A继续执行
- 当前资源忙,T_A主动放弃当前时间片,调度器收到提示切换上下文,T_A挂起
-
static void sleep()
一定会执行,挂起一定时间 -
static Thread currentThread()
返回执行当前代码的线程 -
void interrupt()
主动打断线程阻塞状态 -
boolean isInterrupted()
执行isInterrupted(false)
返回 if this thread has been interrupted; 即线程是否被打断过 -
static boolean interrupted()
实际上执行currentThread().isInterrupted(true);
即返回当前线程的interrupted并复位interrupted状态 -
native boolean isInterrupted(boolean ClearInterrupted)
线程是否被打断,同时是否复位interrupted标识
网友评论