1.实现线程的三种方式:
继承Thread类(无返回值):
public class ThreadTest {
/**
* 继承Thread类
*/
public static class MyThread extends Thread {
@Override
public void run() {
System.out.println("This is child thread");
}
}
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
实现Runnable接口(无返回值):
public class RunnableTask implements Runnable {
public void run() {
System.out.println("Runnable!");
}
public static void main(String[] args) {
RunnableTask task = new RunnableTask();
new Thread(task).start();
}
}
实现Callable接口,这里是要重写call()方法,使用FutureTask创建线程:
public class CallerTask implements Callable<String> {
public String call() throws Exception {
return "Hello";
}
public static void main(String[] args) {
//创建异步任务
FutureTask<String> task=new FutureTask<String>(new CallerTask());
//启动线程
new Thread(task).start();
//获取返回结果
String result=task.get();
System.out.println(result);
}
}
2.为什么要调用start方法?
因为start方法是启动一个线程的意思,如果直接去调用run方法,相当于在main线程种调用一个方法,还是在main线程种执行
3.线程等待常用方法:
wait(): 线程调用该方法时,会发生阻塞,直到被唤醒。
wait(Long timeout): timeout为线程的阻塞超时时间,在该时间内,如果没有被唤醒,会因为超时而被返回。
join(): 假如在main线程中,创建了一个线程A,执行了A.Start(),A.join(),则main线程会放弃cpu控制权,等线程A执行完了,才会继续去执行main线程。
4.线程常用的唤醒方法:
notify(): 随机唤醒一个在共享变量上调用了wait方法的线程。
notifyAll() : 唤醒全部在共享变量上调用了wait方法的线程。
5.线程睡眠的方法:
sleep(long millis) : 线程调用该方法后,在时间内让出执行权,但是资源是不会释放的,时间到后,接着正常执行
6.线程让出优先权:
yield() : 线程调用 yield 方法时,实际就是在暗示线程调度器当前线程请求让出自己的CPU ,但是线程调度器可以无条件忽略这个暗示。
7.守护线程:
java中线程分为守护线程和用户线程,常见的用户线程就是main,守护线程就是垃圾回收。守护线程和用户线程的区别就是,当最后一个用户线程退出后,JVM会退出,而守护线程不会影响JVM的退出。
8.线程间的通信:
-
关键字:
volatile: 用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。
synchronized: 用来修饰字段(成员变量),就是告知程序任何对该变量的访问均需要从共享内存中获取,而对它的改变必须同步刷新回共享内存,它能保证所有线程对变量访问的可见性。 -
等待/通知机制:
就是前面所说了wait和notify,等待唤醒。 -
管道:
管道输入/输出流主要包括了如下4种具体实现:PipedOutputStream、PipedInputStream、 PipedReader和PipedWriter,前两种面向字节,而后两种面向字符,传输的媒介为内存。 -
join():
上面也说过。 -
ThreadLocal:
也就是线程本地变量。如果你创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是操作自己本地内存里面的变量,从而起到线程隔离的作用,避免了线程安全问题。
原子性、可见性、有序性:
原子性: 原子性指的是一个操作是不可分割、不可中断的,要么全部执行并且执行的过程不会被任何因素打断,要么就全不执行。
可见性: 可见性指的是一个线程修改了某一个共享变量的值时,其它线程能够立即知道这个修改。
有序性: 有序性指的是对于一个线程的执行代码,从前往后依次执行,单线程下可以认为程序是有序的,但是并发时有可能会发生指令重排。