文章目录
创建线程
方法1,直接Thread
// 创建线程对象
Thread t = new Thread() {
public void run() {
// 要执行的任务
}
};
// 启动线程
t.start();
方法2,使用 Runnable 配合 Thread
把【线程】和【任务】(要执行的代码)分开
- Thread 代表线程
- Runnable 可运行的任务(线程要执行的代码)
Runnable runnable = new Runnable() {
public void run(){
// 要执行的任务
}
};
// 创建线程对象
Thread t = new Thread( runnable );
// 启动线程
t.start();
也可使用lambda表达式
// 创建任务对象
Runnable task2 = () -> log.debug("run...");
方法3,FutureTask 配合 Thread
FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况
// 创建任务对象
FutureTask<Integer> task3 = new FutureTask<>(() -> {
log.debug("run");
return 100;
});
// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t5=new Thread(task3, "t5");
t5.start();
// 主线程阻塞,同步等待 task 执行完毕的结果
Integer result = task3.get();
log.debug("结果是:{}", result);
19:22:27 [t3] c.ThreadStarter - run
19:22:27 [main] c.ThreadStarter - 结果是:100
例子测试
public static void main(String[] args) throws ExecutionException, InterruptedException {
Thread t1 =new Thread("t1"){
@Override
public void run() {
log.debug("t1.run...");
}
};
t1.start();
Runnable task1=new Runnable() {
@Override
public void run() {
log.debug("t2.run...");
}
};
Thread t2=new Thread(task1,"t2");
t2.start();
Runnable task2=()->{log.debug("t3.run...");};
Thread t3=new Thread(task2,"t3");
t3,start();
Thread t4=new Thread(()->{log.debug("t4.run...");},"t4");
t4.start();
// 创建任务对象
FutureTask<Integer> task3 = new FutureTask<>(() -> {
log.debug("hello");
return 100;
});
// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t5=new Thread(task3, "t5");
t5.start();
// 主线程阻塞,同步等待 task 执行完毕的结果
Integer result = task3.get();
log.debug("结果是:{}", result);
}
源码分析
Thread与Runnable
- Runnable只是一个接口
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
*在创建线程时,Thread的构造方法
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
- init是重写的方法
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null);
}
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();
}
中间有一行是this.target=target;
将Runnable的对象赋值。
- 调用start方法
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
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 */
}
}
}
- start0方法
private native void start0();
/**
* If this thread was constructed using a separate
* <code>Runnable</code> run object, then that
* <code>Runnable</code> object's <code>run</code> method is called;
* otherwise, this method does nothing and returns.
* <p>
* Subclasses of <code>Thread</code> should override this method.
*
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
最后一个是重点,前面target赋值了,所以不为null可以使用Runnable的run方法
FutureTask与Thread
- FutureTask实现了RunnableFuture< V>
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
- RunnableFuture< V>继承了Runnable,所以可以当作参数传输到Thread里面
- 而且它又继承了Future< V>,里面有get方法可以获得返回值
V get() throws InterruptedException, ExecutionException;
- FutureTask构造时传输了Callable< V>参数,Callable < V > 和Runnable有点像,只是Callable< V >有返回值
Callable < V >
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
- FutureTask在Thread中过程是一样的,最后调用了 FutureTask的run
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
因为通过FutureTask的构造函数初始化了Callable的对象且state赋值了NEW,所以直接进if语句,来调用Callable的call方法,并返回值
结语
Runnable与FutureTask在Thread中过程是一样的,只是前者在新建时将要运行的代码重写到了run方法里面,而FutureTask通过传参Callable并将要运行的代码重写到了Callable的call方法里面,FutureTask内部通过重写继承的Runnable的run方法来调用了Callable的call方法来实现。