线程API
获取线程相关信息的方法
package thread;
/**
* 获取线程相关信息的一组方法
*/
public class ThreadInfoDemo {
public static void main(String[] args) {
Thread main = Thread.currentThread();//获取主线程
String name = main.getName();//获取线程的名字
System.out.println("名字:"+name);
long id = main.getId();//获取该线程的唯一标识
System.out.println("id:"+id);
int priority = main.getPriority();//获取该线程的优先级
System.out.println("优先级:"+priority);
boolean isAlive = main.isAlive();//该线程是否活着
System.out.println("是否活着:"+isAlive);
boolean isDaemon = main.isDaemon();//是否为守护线程
System.out.println("是否为守护线程:"+isDaemon);
boolean isInterrupted = main.isInterrupted();//是否被中断了
System.out.println("是否被中断了:"+isInterrupted);
}
}
线程优先级
线程start后会纳入到线程调度器中统一管理,线程只能被动的被分配时间片并发运行,而无法主动索取时间片.线程调度器尽可能均匀的将时间片分配给每个线程.
线程有10个优先级,使用整数1-10表示
- 1为最小优先级,10为最高优先级.5为默认值
- 调整线程的优先级可以最大程度的干涉获取时间片的几率.优先级越高的线程获取时间片的次数越多,反之则越少.
- Thread提供了对应的常量:MAX_PRIORITY表示最高优先级10,MIN_PRIORITY表示最低优先级,NORM_PRIORITY表示默认优先级5
sleep阻塞
线程提供了一个静态方法:
- static void sleep(long ms)
- 使运行该方法的线程进入阻塞状态指定的毫秒,超时后线程会自动回到RUNNABLE状态等待再次获取时间片并发运行.
sleep方法处理异常:InterruptedException.
当一个线程调用sleep方法处于睡眠阻塞的过程中,该线程的interrupt()方法被调用时,sleep方法会抛出该异常从而打断睡眠阻塞.
守护线程
概念
守护线程也称为:后台线程
- 守护线程是通过普通线程调用setDaemon(boolean on)方法设置而来的,因此创建上与普通线程无异.
- 守护线程的结束时机上有一点与普通线程不同,即:进程的结束.
- 进程结束:当一个进程中的所有普通线程都结束时,进程就会结束,此时会杀掉所有正在运行的守护线程.
用途
- GC就是运行在守护线程上的
- 当我们有一个任务不需要关注何时结束,当程序需要结束时可以一起结束的任务就可以放在守护线程上执行
多线程并发
概念
当多个线程并发操作同一临界资源,由于线程切换时机不确定,导致操作临界资源的顺序出现混乱严重时可能导致系统瘫痪.
临界资源:操作该资源的全过程同时只能被单个线程完成.
synchronized关键字
解决并发安全问题的本质就是将多个线程并发(同时)操作改为同步(排队)操作来解决。
synchronized
是Java中的关键字,用于实现线程之间的同步。它可以用于修饰方法或代码块,以确保在同一时间只有一个线程能够进入被修饰的代码区域。
使用synchronized
可以解决多线程并发访问共享资源时可能出现的竞态条件和数据不一致的问题。当一个线程进入了被synchronized
修饰的代码区域时,它会获取该代码块或方法的锁,其他线程将被阻塞,直到该线程释放锁为止。
使用synchronized
的方式有两种:
-
修饰方法:在方法声明中使用
synchronized
关键字修饰,表示整个方法是一个同步代码块,只能被一个线程执行。public synchronized void method() { // 同步代码块 }
-
修饰代码块:在需要同步的代码块中使用
synchronized
关键字修饰,只对该代码块进行同步,其他非同步的代码可以并发执行。synchronized(同步监视器对象){ 需要多线程同步执行的代码片段 }
同步监视器对象即上锁的对象,要想保证同步块中的代码被多个线程同步运行,则要求多个线程看到的同步监视器对象是同一个.
在静态方法上使用synchronized
当在静态方法上使用synchronized后,该方法是一个同步方法.由于静态方法所属类,所以一定具有同步效果.
静态方法使用的同步监视器对象为当前类的类对象(Class的实例).
互斥锁
当多个线程执行不同的代码片段,但是这些代码片段之间不能同时运行时就要设置为互斥的.
使用synchronized锁定多个代码片段,并且指定的同步监视器是同一个时,这些代码片段之间就是互斥的。
线程池
线程池是管理线程的机制,主要解决两个问题,重复使用线程和控制线程数量。
public class ThreadPoolDemo {
public static void main(String[] args) {
//创建线程池
//创建一个固定大小的线程池,容量为2
ExecutorService threadPool = Executors.newFixedThreadPool(2);
for(int i=0;i<5;i++){
Runnable r = new Runnable() {
public void run() {
try {
Thread t = Thread.currentThread();
System.out.println(t+":正在执行任务...");
Thread.sleep(5000);
System.out.println(t+":执行任务完毕!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threadPool.execute(r);//将任务交给线程池去执行
System.out.println("将一个任务交给了线程池");
}
//关闭线程池,线程池不再接收新任务,等线程池中所有任务都执行后结束
threadPool.shutdown();
//立即关闭线程池,此时线程池会调用线程的中断方法
threadPool.shutdownNow();
System.out.println("线程池关闭了");
}
}