Java多线程及源码学习(一)
前言
进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。(进程是资源分配的最小单位)线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。(线程是cpu调度的最小单位)
一、多线程创建及使用
代码如下:
//创建新线程需实例化Thread,调用start方法
public class ThreadTest extends Thread{
public static void main(String[] args) throws InterruptedException{
Thread t = new ThreadTest();
t.start();
int i =1;
while (i<10){
System.out.println(Thread.currentThread().getName()+":打印"+i);
i++;
}
}
@Override
public synchronized void run() {
int i = 1;
while (i<10){
System.out.println(this.getName()+":打印"+i);
i++;
}
}
}
运行结果
main:打印1
main:打印2
Thread-0:打印1
Thread-0:打印2
Thread-0:打印3
Thread-0:打印4
Thread-0:打印5
Thread-0:打印6
Thread-0:打印7
Thread-0:打印8
Thread-0:打印9
main:打印3
main:打印4
main:打印5
main:打印6
main:打印7
main:打印8
main:打印9
源码阅读
1、构造方法
//Thread构造方法调用init()完成线程属性初始化,继承Thread类的一般调用此构造方法
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
//实现Runnable接口的,一般调用此构造方法
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
2、init()方法
//继续调用重载的init()方法
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
//ThreadGroup线程组,默认为父线程组,target线程运行的内容,name线程名称,stackSize线程栈大小,acc访问控制,inheritThreadLocals判断是否可访问父线程的ThreadLocal
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
//设置线程名称
this.name = name;
//当前运行的线程即该实例父线程
Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
if (g == null) {
/* 判断是否为小应用程序 */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* 线程组为父线程的线程组. */
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);
}
}
//线程组中未启动线程数量+1
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);
//可继承的ThreadLocal
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
this.stackSize = stackSize;
/* 设置线程id */
tid = nextThreadID();
}
3、线程启动start()方法
public synchronized void start() {
//threadStatus状态不为0时报错
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
//通知线程组线程启动
group.add(this);
//标志
boolean started = false;
try {
//本地方法,虚拟机调用
start0();
//未保存,设置成功标志
started = true;
} finally {
try {
if (!started) {
//若失败,通知线程组
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
总结
以上就是要讲的内容,本文仅仅简单阅读了Thread类源码,如有错误请指出,谢谢。