创建线程
继承Thread
@Overridepublic 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() 接口
@FunctionalInterfacepublic 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 接口
@FunctionalInterfacepublic 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());}
