JAVA并发编程知识点
这篇文章主要记录了多线程基础知识,不会对知识点深入探讨,仅供参考。
线程创建
创建线程的方式
继承Thread类
public class ThreadCreate {
public static void main(String[] args) {
// 继承的方式
SubTread subTread = new SubTread();
subTread.start();
System.out.println("主线程已经结束");
}
private static class SubTread extends Thread {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是继承了 Thread 的线程");;
}
}
}
实现Runable接口
public class ThreadCreate {
public static void main(String[] args) {
// 实现Runnable接口
RunnableThread runnableThread = new RunnableThread();
// 直接调用run方法会使主线程等待三秒钟
// runnableThread.run();
// 调用需要使用new Thread()
new Thread(runnableThread).start();
System.out.println("主线程已经结束");
}
private static class RunnableThread implements Runnable {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是实现了 Runnable 接口的线程");
}
}
}
实现Callable接口
public class ThreadCreate {
public static void main(String[] args) {
// 实现Callable接口
CallableThread callableThread = new CallableThread();
FutureTask<CallableThread> futureTask = new FutureTask<CallableThread>(callableThread);
new Thread(futureTask).start();
try {
System.out.println("实现了 Callable 接口的线程,返回值为:" + futureTask.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("主线程已经结束");
}
private static class CallableThread implements Callable {
public Object call() throws Exception {
System.out.println("我是实现了 Callable 的线程");
return "100";
}
}
}
三种创建线程的方式的优缺点
- 对于继承Thread方式
- 优点是:编码实现简单;
- 缺点是:java只支持单集成,继承Thread之后无法集成其他类,扩展性有限制。
- 对于实现Runnable接口方式
- 优点是:规避了单继承问题,可以实现多个接口;
- 缺点是:无法拿到线程的返回值。
- 对于实现Callable接口方式
- 优点是:规避单继承问题,可以实现多个接口;
- 缺点是:编码复杂度更高。
线程的状态
线程的状态有哪些
- new 初始状态
- runnable 运行状态
- ready 就绪状态
- running 运行中
- blocked 阻塞状态
- waiting 等待状态
- time_waiting 超时等待状态
- terminated 线程终止状态
各状态的关系

线程操作
启动线程
调用线程的start()方法。
start()方法和run()方法的区别
start()方法用于启动一个新的线程;run()方法只是一个普通的方法,在主线程中会串行执行。
终止线程
- 调用stop()方法,强制停止线程。这是过期作废的方法,不推荐使用。
- 调用interrupt()方法中断线程。
- 使用退出标志,让线程正常退出。即run()方法执行结束。
interrupt()方法
给线程设置中断标志,并不会立马中断线程。
interrupted()方法与isInterruputed()方法
- interrupted()是获取当前现场是否被中断,并且清除中断位标志。
- isInterrupted()是获取被调用线程是否中断,不清除中断位标志。
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
thread.interrupt();
System.out.println("线程thread是否中断=" + thread.isInterrupted());
System.out.println("线程thread是否中断=" + thread.isInterrupted());
Thread.currentThread().interrupt();
System.out.println("main是否中断=" + thread.interrupted());
// 清除了中断位,所以第二次打印是false
System.out.println("main是否中断=" + thread.interrupted());
} catch (Exception e) {
e.printStackTrace();
}
}
private static class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 500000; ) {
i++;
}
}
}
执行结果
线程thread是否中断=true
线程thread是否中断=true
main是否中断=true
main是否中断=false
线程安全
代码在多线程环境下和单线程环境下,执行的结果相同,代表是线程安全的。
线程和进程的区别
-
从概念上来说,进程是一个“执行中的程序”,是系统进行资源分配和调度的一个独立单位;线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。
-
从CPU层面来说,进程和线程其实都是CPU工作时间段的描述,只不过是颗粒大小不同。
-
从地址空间来说,同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间;
线程之间怎么通信
-
内存共享,在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过读-写内存中的公共状态来隐式的进行通信。
-
消息传递。顾名思义,就是通过明确的发送消息来显式的进行通信。这里又经常会涉及到等待唤醒机制:wait() 和 notify() 等相关问题了。
线程中yield()方法的作用
运行中的线程,让出自己的CPU执行时间,给自己或者其他线程使用。不是单纯的让给其他线程,有可能自己马上就能获取到CPU的使用权。
yield()方法与sleep()方法的区别
-
从线程优先级来说,yield()方法只会给相同优先级或者更高优先级的线程运行机会;但是,sleep()方法给其他线程运行机会时不考虑线程的优先级,因此也会给优先级低的线程运行的机会。
-
从运行后状态来说,运行yield()方法之后,线程回到就绪状态,可能又马上被执行;但是,如果执行sleep()方法后,线程会转入time_waiting状态,在指定的时间内肯定不会被执行。
-
从抛出异常来说,yield()方法没有声明任何异常;而sleep()方法声明抛出InterruptedException。
-
从可移植性上来说,sleep()方法比yield()方法具有更好的可移植性。
线程池
创建线程池的方式
newCachedThreadPool
创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行
很多短期异步任务的程序而言,这些线程池通常可提高程序性能。 调用 execute 将重用以前构造
的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并
从缓存中移除那些已有 60 秒钟未被使用的线程。 因此,长时间保持空闲的线程池不会使用任何资
源。
newFixedThreadPool
创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大
多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,
则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何
线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之
前,池中的线程将一直存在。
newScheduledThreadPool
创建一个线程池,给定延迟时间,执行命令或者定期执行命令。
newSingleThreadExecutor
Executors.newSingleThreadExecutor()返回一个线程池(这个线程池只有一个线程) ,这个线程
池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去!

浙公网安备 33010602011771号