创建线程
继承Thread
@Override
public void run() {
System.out.println("MyThread");
}
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.start();
}
再调用start() 方法之后,该线程才能启动,虚拟机会会先为我们创建一个线程,等到这个线程第一次获取到时间片再调用run()方法。
不能重复调用start()方法,重复调用会抛出 IllegalThreadStateException 异常
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();
}
实现Runnable() 接口
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
可以看到Runnable 是一个函数式接口,这意味着我们可以使用Java 8 的函数式编程来简化代码
public static void main(String[] args) {
new Thread(() -> System.out.println("hello world")).start();
}
通常来说,我们使用Runnable 和Thread 来创建一个新的线程,但他们都有一个弊端,就是run()没有返回值, 有时候我们希望开启一个线程去执行一个任务,并且执行任务后有一个返回值。
Callable 接口
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
Callable 一般配合线程池工具 ExecutorService来使用。
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
Future<Integer> future = executorService.submit(() -> 2);
//注意调用get()方法会阻塞当前线程,直到得到结果
System.out.println(future.get());
}
Future 接口
public interface Future<V> {
/**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when {@code cancel} is called,
* this task should never run. If the task has already started,
* then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return {@code true}. Subsequent calls to {@link #isCancelled}
* will always return {@code true} if this method returned {@code true}.
*
* @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
* {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
* Returns {@code true} if this task was cancelled before it completed
* normally.
*
* @return {@code true} if this task was cancelled before it completed
*/
boolean isCancelled();
/**
* Returns {@code true} if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
* {@code true}.
*
* @return {@code true} if this task completed
*/
boolean isDone();
/**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
*/
V get() throws InterruptedException, ExecutionException;
/**
* Waits if necessary for at most the given time for the computation
* to complete, and then retrieves its result, if available.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
* @return the computed result
* @throws CancellationException if the computation was cancelled
* @throws ExecutionException if the computation threw an
* exception
* @throws InterruptedException if the current thread was interrupted
* while waiting
* @throws TimeoutException if the wait timed out
*/
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
cancel()方法是试图取消一个线程的执行,是试图取消,并不一定取得成功
线程组(ThreadGroup)
Java中用ThreadGroup来表示线程组,我们可以使用线程组对线程进行批量控制。
每一个线程必然存在于一个ThreadGroup 中,Thread 不能独立于ThreadGroup 存在,如果没有显式指定,那么默认将父线程设置为自己的线程组。
public static void main(String[] args) { // ThreadGroup 是main new Thread(() -> System.out.println(Thread.currentThread().getThreadGroup().getName())).start(); System.out.println(ThreadDemo.currentThread().getName()); }
ThreadGroup 是一个标准的向下引用的数状结构,这样子设计的原因是防止”上级”线程被下级线程引用而无法有效地被GC 回收。
线程的优先级
Java 的线程的优先级可以指定,范围是1~10 .默认优先级为 5,。但是不是所有的操作系统都支持10级优先级,Java只是给操作系统一个参考值,线程最终在操作系统的优先级是多少还是有操作系统来决定的。
优先级更高的线程有更好的机率得到执行。
如果某个线程的优先级大于线程所在组的最大优先级,那个该线程的优先级将会失效,取而代之的是线程组的最大优先级。
守护线程
守护线程的默认优先级比较低,如果所有的非守护线程都结束了,这个守护线程也会自动结束。
线程常用方法
sleep()
yield()
放弃当前的CPU 执行的时间片,让其他线程执行
interrupt()
仅仅作为子线程的中断标志,子线程并没有真正中断,配合 isInterrupted() 方法一起使用
state()
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
if (Thread.interrupted()) {
return;
}
System.out.println("00000");
});
thread.start();
thread.interrupt();
Thread.sleep(3000);
System.out.println(thread.getState());
}