java线程的三种创建方式对比

时间:2023-02-17 09:35:04
1. 继承Thread
public class Thread2 extends Thread{

@Override
public void run() {
// TODO Auto-generated method stub
super.run();
}

public static void main(String[] args) {
new Thread2().start();
}
}

2. 实现Runnable接口
public class Thread3 implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub

}
public static void main(String[] args) {
new Thread(new Thread3()).start();
}
}
其中Runnable里面只有一个run方法
publicinterface Runnable {    public abstract void run();}


3. 实现Callable接口,与第二种方法没有什么区别      call方法作为执行主体,比run方法更灵活,可以有返回值,抛出异常
public class thread3 implements Callable<String>{

@Override
public String call() throws Exception {
// TODO Auto-generated method stub
return null;
}

public static void main(String[] args) {
thread3 t3 = new thread3();
FutureTask<String> futureTask = new FutureTask<String>(t3);
new Thread(futureTask).start();
}
}

4. 下面看一下Thread类源码:
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}

public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}

public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
Thread的初始化函数最终都会调用下面的init方法
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
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();
this.name = name.toCharArray();
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
this.inheritedAccessControlContext = 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();
}

  1.  从上面代码看出thread的parent取得是当前线程,也就是创建该线程的线程
2. 线程的ThreadGroup默认是父线程的
 public ThreadGroup getThreadGroup() {
return Thread.currentThread().getThreadGroup();
}
3. 其他的诸如daemon 、priority都与父线程保持一致,另外尤其说一下name属性
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
/* For autonumbering anonymous threads. */    private static int threadInitNumber;    private static synchronized int nextThreadNum() {return threadInitNumber++;    }
所以如果创建线程时没有显示指定线程名,迷人的线程名就会是Thread1,Thread3......

4. Thread.GetCurrentThread.getName5. 线程的5种状态     准备 就绪 阻塞 执行 结束6. 线程优先级优先级高的线程被调度的概率大,也不是一定优先级高的线程会先于优先级低的线程调用,具体看JVM的调度策略