爱站网app,wordpress采集插件 中文,个人求职网页制作,网站的排版问题文章目录synchronized 锁有两种synchronized异常捕获主线程和子线程volatile的作用notify是随机启动等待线程中的一个synchronized 锁有两种
类对象类的实例
第一种#xff1a;锁类对象#xff0c;有两种方式#xff0c;如下#xff1a;
// 方法一#xff1a;synchroni…
文章目录synchronized 锁有两种synchronized异常捕获主线程和子线程volatile的作用notify是随机启动等待线程中的一个synchronized 锁有两种
类对象类的实例
第一种锁类对象有两种方式如下
// 方法一synchronized 修饰static方法
public static synchronized void test(){System.out.println(Thread.currentThread().getName() start );try {TimeUnit.SECONDS.sleep(2);} catch (Exception e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() end );
}
// 方法二synchronized锁class对象
public void test2(){synchronized (getClass()) {try {TimeUnit.SECONDS.sleep(2);} catch (Exception e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() run );}
}public static void main(String[] args) {TestThread10 t new TestThread10();new Thread(()-TestThread10.test(),线程 1 ).start();new Thread(()-t.test2(),线程 2 ).start();
}其结果如下 在线程1也就是先启动线程1且等线程1走完才执行线程2
锁类就可以理解为在类对象上加了一把锁所有加锁的方法都需要等待上一把锁的释放才能执行
第二种类的实例
只要对同一个实例对象加锁了才能实现线程同步如下
public void test2(){synchronized (this) {try {TimeUnit.SECONDS.sleep(2);} catch (Exception e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() run );}
}synchronized异常捕获
使用synchronized的时候出现异常一定要处理不然他会自动释放锁 它的机制是手动加锁自动释放锁。下面看一个例子在异常的地方一定要处理异常不然就会想下面代码中的线程1会被释放掉。
private Integer c 0;Override
public void run() {count();
}private synchronized void count(){System.out.println(Thread.currentThread().getName() start。。。);while (true) {System.out.println(Thread.currentThread().getName() countc);try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}if (c 5) {int i 1/0;}}}public static void main(String[] args) {TestThread3 t new TestThread3();Thread t1 new Thread(t, 线程 1);Thread t2 new Thread(t, 线程 2);t1.start();t2.start();
} 主线程和子线程
线程分用户线程和守护线程
main方法其实是一个主线程在操作系统启动java.exe后是开启了一个进程然后进程启动main线程main线程有启动其他线程。
守护线程和主线程一起结束主线程结束守护线程也结束用户线程非守护线程但所有的用户线程结束主线程结束
t2.setDaemon(true);
t2.start();volatile的作用
可以看这位博主的博客Java中Volatile关键字详解 - 郑斌blog - 博客园 (cnblogs.com)
它有两个功能
线程间的可见性防止指令重排序
注意
可见性不代表原子性它只是能够让其他线程能够实时查看到最新值而其他操作它不保证。
指令重排序这个有点深奥可以先暂时忽略
notify是随机启动等待线程中的一个
notify是随机启动等待线程中的一个并且跟线程优先级无关且 wait和notify方法要在同一把lock的情况下使用还有一点是lock.wait 阻塞还后会把锁让出给需要的线程然而在其他线程执行完后调用lock.notify()唤醒等待的线程但是在当前锁里的代码没执行完不会释放掉锁。
简单场景模拟
一个固定容量同步容器拥有put和get方法以及getCount方法能够支持两个生产者线程以及10个消费者线程的阻塞调用。
public class TestThread8 {
private final LinkedList list new LinkedList();private final int MAX 10;private int count 0;public synchronized void put(Object o) {while (list.size() MAX) {try {// 在这里等待的那个调用notify时会从这里继续执行this.wait();} catch (InterruptedException e) {e.printStackTrace();}}list.add(o);count;// 启动所有线程包括生产者随机的this.notifyAll();
}public synchronized void get() {while (list.size() 0) {try {this.wait();} catch (InterruptedException e) {e.printStackTrace();}}list.removeLast();count--;this.notifyAll();
}public int getCount() {return list.size();
}public static void main(String[] args) {TestThread8 t new TestThread8();for (int i 0; i 2; i) {new Thread(() - {int j 0;while (true) {t.put(Thread.currentThread().getName() put t.getCount());System.out.println(Thread.currentThread().getName() put t.getCount());}}).start();}for (int i 0; i 10; i) {new Thread(() - {while (true) {t.get();System.out.println(Thread.currentThread().getName() get t.getCount());}}).start();}
}
}