java多线程编程,Thread,Runnable,Future相关知识

java多线程编程,Thread,Runnable,Future相关知识

一.Thread

A thread is a thread of execution in a program.
The Java Virtual Machine allows an application to have mutliple threads of
execution running concurrently.

There are two way to create an new thread of execution.
One is to declare a class to be a subclass of Thread. This subclass should 
override the run method of class Thread. An instance of the subclass can then
be allocated and started .
For example:

class PrimeThread extends Thread {
	long minPrime;
	PrimeThread(long minPrime) {
		this.minPrime = minPrime;
	}
	public void run() {
		// computer primes larger than minPrime
	}
} 

The following code would then create a thread and start it running:

PrimeThread p = new PrimeThread(143);
p.start();

The other way to create a thread is to declare a class
that implements the Runnable interface. 
That class then implements the run method.
An instance of the class can then be allocated, passed as an argument 
when creating Thread, and started.
For example:

class PrimeRun implements Runnable {
	long minPrime;
	PrimeRun(long minPrime) {
		this.minPrime = minPrime;
	}
    public void run() {
    	// compute primes large than minPrime
    }
}

The folloing code would then create a thread and start it running:

PrimeRun p = new PrimeRun(143);
new Thread(p).start();

二.Runnable

The Runnable interface should be implemented by any class
whose instance are intended to be executed by a therad.
The class must define a method of no arguments called run.

public interface Runnable {
	/**
	*When an object implementing interface Runnnable is used
	* to create a thread, starting the thread causes the object's
	* run method to be called in that separately executing thread.
	*/
	public abstract void run();
}

三.Future

A Future represents the result of an asynchronous computation.


Methods are provided to check if the computation is complete.
to wait for its completion, and to retrieve the result of the computation.
The result can only be retrieved using method get when the compution
has completed, blocking if necessary until it is ready.
Cancellation is performed by the cancel method.
Additional methods are provided to determine if the task completed normally
or was cancelled. Once a computation has completed, the computation
cannot be cancelled.
If you would like to use a Future for the sake of cancellability but not provide a usable result, you can declare types of the form Future<?> and return null as a result of the underlying task.

Sample Usage:

interface ArchiveSearcher {
	String search(String target);
}

class App {
	ExecutorService executor = ...
	ArchiveSearcher searcher = ...
	void showSearch(final String target) thows InterruptedException {
		Future<Stirng> future = executor.submit (new Callable<String>() {
														public String call () {
																		return searcher.search(target);
																	}});
		displayOtherThings(); // do other things while searching
		try {
			displayText(future.get()); // use future
		} catch (ExecutionException ex) {
			cleanup();
			return;
		}
	}
}

The FutureTask class is an implementation of Future that implements Runnable,
and so may be executed by an Executor.
For example, the above construction with submit could be replaced by:

FutureTask<String> future = new FutureTask<>( new Callable<String>() {
	public String call() {
		return searcher.search(target);
	}});
executor.execute(futrue);

参考:Java Future的实现原理
https://www.jianshu.com/p/69a6ae850736

四. FutureTask

A cancellable asynchronous computation.


This class provides a base implement of Future, with methods to start and
cancel a computation, query to see if the computation is complete, and retrieve the result of the computation. The result can only be retrieved when the computation has completed; the get methods will block if the computation has not yet completed.Once the computaion has completed, the computation cannot be restarted or canceled (unless the computation is invoked using runAndReset)


A FutureTask can be used to wrap a Callable or Runnable Object. Because FutureTask implements Runnable, a FutureTask can be submitted to an Executor for execution.

4.1 FutureTask 类内部重要逻辑

public class FutureTask<V> implements RunnableFuture<V> {
	/**
	* The run state of this task, initially NEW. The run state transitions to a terminal
	* state only in methods set, setException, and cancel.
	* During completion, state may take on transient value COMPLETING(while outcome
	* is beging set) or INTERRUPTTING(only while interrupting the runner to satisfy a 
	*  cancel(ture)). Transitions from these intermediate to final states use cheaper 
	* ordered/lazy writes because values are unique and cannot be further modified.
    *
    * Possible state transitions:
     * NEW -> COMPLETING -> NORMAL
     * NEW -> COMPLETING -> EXCEPTIONAL
     * NEW -> CANCELLED
     * NEW -> INTERRUPTING -> INTERRUPTED
	* 
	*/
	private volatile int state;
    private static final int NEW          = 0;
    private static final int COMPLETING   = 1;
    private static final int NORMAL       = 2;
    private static final int EXCEPTIONAL  = 3;
    private static final int CANCELLED    = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED  = 6;

 / **  The underlaying callable; nulled out afther running */
 private Callable<V> callable;
 /** The result to return or exception to throw from get() */
 private Object outcome; // non-volatile, protected by state reads/writes
 /** The thread running the callable; CASed during run() */
 
 ...

/** 
* Return result or throws exception for completed task.
* @param s completed state value
*/
private V report(int s) throws ExcutionException {
	Object x = outcome;
	if (s ==NORMAL) {
		return (V) x;
	}
	if (s >= CANCELLED) {
		throw new CancellationException;
	}
	throw new ExcutionException((Throwable)x);
}

/**
* Create a FutureTask that will, upon running, execute the give Callable
* 
* @param callable the callable task
* @throws  NullPointerException if the callable is null
*/
public FuthreTask(Callable<V> callable) {
	if (callable == null) {
		throw new NullPointerException();
	}
	this.callable = callable;
	this.state = NEW; // ensure visibility of callable
}

...

public V get() throws InterruptedException, ExecutionException {
	int s = state;
	if (s <= COMPLETTING) {
		s = awaitDone(fale, 0L);
	}
	return report(s);
}

...

/**
* Sets the result of this future to the given value unless
* this future has already been set or has been cancelled.
*
* <p> This method is invoked internally by the {#run} method
* upon successful completion of the computation.
*
*@param v the value
*/
protected void set(V v) {
	if(U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
		outcome = v;
		U.putOrderedInt(this, STATE, NORMAL); // final state
		finishCompletion();
	}
}

...

/**
* Awaits completion or aborts on interrupt or timeout.
*
*@param thimed true if use timed waits
*@param tiem to wait, if timed
* @return state upon completion or at timeout
*/
private int awaitDone(boolean timed, long nanos) throws InterruptedException {
	// The code below is very delicate, to achive the goals:
	// -call nanoTime exactly once for each call to park
	// -if nanos <= 0L, return promptly without allocation or nanoTime 
	// -if nanos == Long.MIN_VALUE, don't underflow
	// -if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic
	// and we suffer a spurious wakeup, we will do no worse than
	// to park-spin for a while
	long startTime = 0L;  // Special value 0L means not yet parked
	WaitNode q = null;
	boolean queued = false;
	for(;;) {
		int s = state;
		if (s > COMPLETING) {
			if(q != null) {
				q.thread = null;
			}
			return s;
		} else if (s == COMPLETING) {
			// We may have already promised(via isDone) that we are done
			// So never return empty-handed or throw InterruptedException
			Thread.yield();
		} else if (Thread.interrupted()) {
			removeWaiter(q);
			throw new InterruptedException();
		} else if (q == null) {
			if (timed && nanos <= 0L) {
				return s;
			}
			q = new WaitNode();
		} else if (!queued) {
			queued = U.compareAndSwapObject(this, WAITERS, q.next = waiters, q);
		} else if (timed) {
			final long parkNanos;
			if (startTime == 0L) { // first time
				startTime = System.nanoTime();
				if (startTime == 0L) {
					startTime = 1L;
				}
				parkNanos = nanos;
			} else {
				long elapsed = System.nanoTime() - startTime;
				if (elapse >= nanos) {
					removeWaiter(q);
					return state;
				}
				parkNanos = nanos - elapsed;
			}
			// nanoTime may be slow; recheck before parking
			if (state < COMPLETING) {
				LockSupport.parkNanos(this, parkNanos);
			}
		} else {
			LockSupport.park(this);
		}
	}
	
}


 
	
}

五. Callable

A task that returns a result and may throw an exception.
Implementors define a single method with no arguments called call.


The Callable interface is simmilar to Runnable, in that both are designed for classes whose instances are potentially executed by another thread.
A Runnable, however, does not return a result and cannot throw a checked exception.

/**
* @param <V> the result type of method call
*/
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() throw Exception;
}

六. Executor

A object that executes submitted Runnable tasks.
This interface provides a way of decouping task submission from the mechanics of how each task will be run, including details of thread use, scheduling, etc.
An Executor is normally used instead of explicitly creating threads.
For example, rather than invoking {new Thread(new RunnableTask()).start()} for each of a set of tasks, you might use:

Executor executor = anExecutor();
executor.execute(new RunnableTask1());
executor.execute(new RunnableTask2());

However, the Executor interface does not strictly require that execution be asynchronous. In the simpest case, an executor can run the submitted task immeditely in the caller’s thread:

class DirectExecutor implements Executor {
	public void execute(Runnable r) {
		r.run();
	}
}

More typically, tasks are executed in some thread other than the caller’s thread. The executor below spawn a new thread for each task.

class ThreadPerTaskExecutor implements Executor {
	public void execute(Runnable r) {
		new Thread(r).start();
	}
}

Many Executor implementations impose some sort of limitation on how and when tasks are scheduled. The executor below serializes the submission of tasks to a second executor, inllustrating a coposite executor.

class SerialExecutor implements Executor {
	final Queue<Runnable> tasks = new ArrayDeque<>();
	final Executor executor;
	Runnable active;

	SeriaExecutor(Executor executor) {
		this.executor = executor;
	}
	
	pulic synchronized void execute(final Runnable r) {
		tasks.add(new Runnable() {
			public void run() {
				try {
					r.run():
				} finally {
					scheduleNext();
				}
			}
		});
		if (active == null) {
			scheduleNext();
		}
	} 

	protected synchronized void scheduleNext() {
		if((active = tasks.poll()) != null) {
			executor.execute(active);
		}
	}
}

The Executor implementions provided in this package implement ExecutorService, which is a more extensive interface. The ThreadPoolExecutor class provides an extensible thread pool implementation. The Executors class provides convenient factory methods for these Executors.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值