线程池
核心数量满时,陷入队列,再入非核心,
io密集式线程池线程数量为cup2
cpu密集时线程池数量为cpu核数
*进程与线程
进程是一个具有一定独立功能的程序,是操作系统动态执行的基本单元。
线程是操作系统能够进行运算的最小单位,它被包含在进程中。
实现多线程两种方法
继承Thread倾向于多个线程完成各自任务,实现Runnable倾向于多个线程完成一个任务(由其statr方法决定)
多线程中代码执行顺序与调用顺序无关
要使用p.start不是run
继承Thread,重写run方法
public class demo {
public static void main(String[] args) {
PrimeThread p1 = new PrimeThread(1);
PrimeThread p2 = new PrimeThread(2);
PrimeThread p3 = new PrimeThread(3);
PrimeThread p4 = new PrimeThread(4);
PrimeThread p5 = new PrimeThread(5);
p1.start();
p1.start();
p1.start();
p1.start();
p1.start();
System.out.println("完成");
}
}
class PrimeThread extends Thread{
long minPrime;
PrimeThread(long minPrime){
this.minPrime = minPrime;
}
@Override
public void run(){
//实际业务代码
System.out.println("val="+minPrime);
}
}
实现Runnable,重写run方法
public class demo {
public static void main(String[] args) {
PrimeThread p1 = new PrimeThread(1);
Thread thread = new Thread(p1);
thread.start();
System.out.println("完成");
}
}
class PrimeThread implements Runnable{
long val;
PrimeThread(long val){
this.val = val;
}
@Override
public void run() {
System.out.println("val="+val);
}
}设置线程优先级
优先级为1-10 Thread.currentThread().getPriority(8); Thread.currentThread().setPriority(1);
守护线程
当没有用户线程时守护线程会自动销毁,如垃圾回收线程
public class demo1 {
public static void main(String[] args) throws InterruptedException {
DefendThread defendThread = new DefendThread();
Thread thread = new Thread(defendThread);
thread.setDaemon(true);//把线程设置为守护线程 要在start前设置
thread.start();
Thread.sleep(1000);
System.out.println("主线程在输出完这一行后就结束了");
}
}
class DefendThread implements Runnable{
@Override
public void run() {
while (true){
System.out.println(System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}线程同步机制
线程同步机制用来解决多线程的线程安全问题
synchronized同步方法
非线程安全就是当多个线程访问同一个成员变量时,可能会产生脏读等问题。
线程安全就是获取的成员变量经过同步处理,不会脏读。
局部变量永远是线程安全的
如果有多个线程同时操作业务对象中的成员变量,可能会出现非线程安全。在方法前加上synchronized关键字能保证线程安全。
synchronized取得的是对象锁,当多个线程同时操作一个对象时,有synchronized标识的方法必须依次执行,不能同时执行。没有synchronized标识的方法,可以同时执行。
锁重入机制,在一个被synchronized修饰的方法中调用另一个被synchronized修饰的方法,可以立即执行,没有必要等到当前方法执行完在执行。
锁的释放机制:当一个线程执行的代码出现异常,它所持有的锁会自动释放
同步不具有继承性
Synchronized同步代码块比synchronized声明方法效率要高。Synchronized(object){}的形式存在,不同线程操作同一对象时只会竞争同一object的同步代码块,即如果object不同的两个代码块可以同时执行。
synchronized 锁不同就异步 synchronized对static类是class锁,对非静态类是对象锁,所以对于同时synchronized标识的静态方法与非静态方法,执行异步。
重入锁:为了避免死锁,当线程获取一个对象锁,该线程可以再次获取该对象锁。synchronized就是重入锁。例如在一个synchronized声明的同步代码块中可以调用其他的同步代码块,而不会死锁。原理,每个锁关联一个计数器和占有它的线程,当计数器为0代表锁未被占用,当线程占有锁计数器置为1,当再次占用计数器依次递增。当线退出同步代码块时,计数器递减,直至为0,释放锁。
volatile 线程同步轻量级的实现,性能比synchronized好,但只能修饰变量不能修饰方法。
通知和等待机制 wait/notify机制
wait方法使当前正在执行的线程进入等待状态,将当前线程放入预执行队列,并且在wait所在的代码行停止执行,直到被通知或被中断,在继续从中断的位置开始继续执行,而不是从头执行。wait只能在同步代码块中调用。执行wait后当前锁会释放掉。
notify方法也只能在同步代码块中调用,当有多个线程等待,会由线程调试器随机挑选一个wait状态的线程发出通知。执行notify后要等到所在synchronized代码块执行完,才会通知到wait。object.notify随即唤醒一个,object.notifyAll()唤醒object对象锁所有处于wait状态的。
wait(long)和sleep(long)很相似,但是wait释放对象锁,sleep不释放对象锁。
public class demo2 {
public static void main(String[] args) {
Object object = new Object();
DemoThread demoThread = new DemoThread(object);
new Thread(demoThread).start();
Demo1Thread demo1Thread = new Demo1Thread(object);
new Thread(demo1Thread).start();
}
}
class DemoThread implements Runnable{
private Object object;
public DemoThread(Object object){
this.object = object;
}
@Override
public void run() {
synchronized(object){
System.out.println("wait开始");
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("wait结束");
}
}
}
class Demo1Thread implements Runnable{
private Object object;
public Demo1Thread(Object object){
this.object = object;
}
@Override
public void run() {
synchronized (object){
System.out.println("notify开始");
object.notify();
System.out.println("notify结束");
}
}
}
京公网安备 11010502036488号