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方法
public
interface 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.getName
5. 线程的5种状态
准备 就绪 阻塞 执行 结束
6. 线程优先级
优先级高的线程被调度的概率大,也不是一定优先级高的线程会先于优先级低的线程调用,具体看JVM的调度策略