每个线程:
- 拥有自己的计数器
- 自己的堆栈、局部变量
- 能够访问共享的内存变量
处理器在这些线程上高速切换,让使用这感到这些线程在同时执行。
1 - 为什么使用多线程
主要有以下几点:
更多的处理器核心
处理器的核心数量越来越多,以及超线程的运用,现在大多数计算机比之前更加擅长并行计算
。处理器性能提升的方式,也向更多的核心发展。
线程是大多数操作系统调度的基本单元。一个线程在一个时刻,只能运行在一个处理器核心上。
更快的响应时间
一些较为复杂的业务代码,比如,一笔订单的创建,包括插入订单数据、生成订单快照、发送邮件通知卖家、记录销售数量等。用户从单机订购按钮开始,
就要等待这些操作全部完成才能看到订购成功的结果。
上面的场景中,使用多线程,将数据一致性不强的操作派发给其他线程处理(也可以是消息队列),如生成订单快照、发送邮件等。这样做的好处是响应
用户请求的线程能够尽快的处理完成。缩短了响应时间。
2 - 线程优先级
线程优先级:线程需要多或者少的分配一些处理器资源的线程属性。
- 操作系统分出一个个时间片
- 线程会分配到若干时间片
- 当线程的时间片用完了就会发生线程调度,并等待下次分配
- 线程分配到的时间片的多少也就决定了线程使用处理器资源的多少
优先级高的线程分配到的时间片数量要多于优先级低的线程。
3 - 线程中断
public static void main(String[] args) throws InterruptedException {
Thread sleepThread = new Thread(new SleepRunner(), "SleepThread");
sleepThread.setDaemon(true);
Thread busyThread = new Thread(new BusyRunner(), "BusyThread");
busyThread.setDaemon(true);
sleepThread.start();
busyThread.start();
// 休眠5秒 让两个线程充分运行
TimeUnit.SECONDS.sleep(5);
// 中断相当于线程的一个标志位
// 表示一个运行中的线程, 是否被其他线程执行了中断操作
// 其他线程通过调用线程的interrupt方法
// 对线程进行中断操作
sleepThread.interrupt();
busyThread.interrupt();
System.out.println("SleepThread interrupted is " + sleepThread.isInterrupted());
System.out.println("BusyThread interrupted is " + busyThread.isInterrupted());
// 防止两个线程立刻退出
SleepUtils.second(30);
busyThread.interrupted();
System.out.println("BusyThread interrupted is " + busyThread.isInterrupted());
SleepUtils.second(3);
System.out.println("程序退出");
/*
* 这种通过标志位或者中断的方式能够使线程在终止时能够使线程有机会
* 清理一些资源, 而不是武断的去停止, 这种终止线程的方式更加安全和优雅
*/
}
static class SleepRunner implements Runnable {
@Override
public void run() {
while (true) {
SleepUtils.second(3);
}
}
}
static class BusyRunner implements Runnable {
@Override
public void run() {
while (true) {
//System.out.println("ddd ");
}
}
}
public static void main(String[] args) {
Runner r = new Runner();
Thread countThread = new Thread(r, "CountThread");
countThread.start();
// 休眠一秒钟 main线程对CountThread进行中断
// CountThread能够感知中断而结束
SleepUtils.second(1);
countThread.interrupt();
Runner two = new Runner();
countThread = new Thread(two, "CountThread");
countThread.start();
SleepUtils.second(1);
two.cancle();
}
static class Runner implements Runnable {
private long i = 0;
private volatile boolean on = true;
@Override
public void run() {
while (on && !Thread.currentThread().isInterrupted()) {
i++;
}
System.out.println("count: " + i);
}
public void cancle() {
on = false;
}
}
public static void main(String[] args) {
new Thread(new TimeWaiting(), "TimeWaitingThread").start();
new Thread(new Waiting(), "WaitingThread").start();
new Thread(new Blocked(), "BlockedThread-1").start();
new Thread(new Blocked(), "BlockedThread-2").start();
}
static class TimeWaiting implements Runnable {
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName());
SleepUtils.second(100);
}
}
}
static class Waiting implements Runnable{
@Override
public void run() {
while (true) {
synchronized (Waiting.class) {
try {
System.out.println(Thread.currentThread().getName());
Waiting.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class Blocked implements Runnable {
@Override
public void run() {
synchronized (Blocked.class) {
while (true) {
System.out.println(Thread.currentThread().getName());
SleepUtils.second(100);
}
}
}
}
private static Object lock = new Object();
private static boolean flag = true;
public static void main(String[] args) {
new Thread(new Wait(), "WaitThread").start();
SleepUtils.second(1);
new Thread(new Notify(), "NotifyThread").start();
}
static class Wait implements Runnable {
@Override
public void run() {
synchronized (lock) {
while (flag) {
String msg = Thread.currentThread() + " flag is true, wait @ " +
new SimpleDateFormat("HH:mm:ss:sss").format(new Date());
System.out.println(msg);
try {
/**
* wait()方法调用后, 该线程进入waitting状态, 只有等待另外的线程通知或被中断才会返回
* 并且会释放这个对象上的锁
* 线程状态由ROUNNING变成WAITTING, 并将当前线程放入lock的等待队列中, 然后释放lock上的锁
*/
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
msg = Thread.currentThread() + " wait后的代码执行 @ " + new SimpleDateFormat("HH:mm:ss:sss").format(new Date());
System.out.println(msg);
}
String msg = Thread.currentThread() + " flag is false, running @ " +
new SimpleDateFormat("HH:mm:ss:sss").format(new Date());
System.out.println(msg);
}
}
}
static class Notify implements Runnable {
@Override
public void run() {
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock, notify @ " + new SimpleDateFormat("HH:mm:ss:sss").format(new Date()));
lock.notifyAll();
flag = false;
SleepUtils.second(5);
}
synchronized (lock) {
System.out.println(Thread.currentThread() + " hold lock again, sleep @ " + new SimpleDateFormat("HH:mm:ss:sss").format(new Date()));
SleepUtils.second(5);
}
}
}