JAVA多线程 & 同步关键词synchronized & ReadWriteLock读写文件 在java中可有两种方式实现多线程,一种是继承Thread类,一种是实现Runnable接口;Thread类是在java.lang包中定义的。一个类只要继承了Thread类同时覆写了本类中的run()方法就可以实现多线程操作了,但是一个类只能继承一个父类,这是此方法的局限。 1 public class Actor extends Thread { 2 public void run(){ 3 //线程执行的操作 4 } 5 } 在实际开发中一个多线程的操作很少使用Thread类,而是通过Runnable接口完成。 1 public class Actress implements Runnable{ 2 3 @Override 4 public void run() { 5 //线程执行的操作 6 } 7 } 在主方法中调用这两种线程。 1 public static void main(String[] args) { 2 Thread actor=new Actor(); 3 actor.setName(“Mr.thread”); //Thread 线程 4 actor.start(); 5 6 Thread actressThread=new Thread(new Actress(),”Miss.Runnable”); //Runnable 线程 7 actressThread.start(); 8 } 两种实现方式的区别和联系: 在程序开发中只要是多线程肯定永远以实现Runnable接口为主,因为实现Runnable接口相比继承Thread类有如下好处: 1、避免点继承的局限,一个类可以继承多个接口。 2、适合于资源的共享 以卖票程序为例,通过Thread类完成: 1 package multithreading; 2 3 public class MyThreadWithExtends extends Thread { 4 5 private int tickets = 10; 6 7 @Override 8 public void run() { 9 10 for (int i = 0; i <= 100; i++) { 11 if(tickets>0){ 12 System.out.println(Thread.currentThread().getName()+”–卖出票:” + tickets–); 13 } 14 } 15 } 16 17 18 public static void main(String[] args) { 19 MyThreadWithExtends thread1 = new MyThreadWithExtends(); 20 MyThreadWithExtends thread2 = new MyThreadWithExtends(); 21 MyThreadWithExtends thread3 = new MyThreadWithExtends(); 22 23 thread1.start(); 24 thread2.start(); 25 thread3.start(); 26 27 //每个线程都独立,不共享资源,每个线程都卖出了10张票,总共卖出了30张。如果真卖票,就有问题了。 28 } 29 30 } 运行结果: Thread-0–卖出票:10 Thread-2–卖出票:10 Thread-1–卖出票:10 Thread-2–卖出票:9 Thread-0–卖出票:9 Thread-2–卖出票:8 Thread-1–卖出票:9 Thread-2–卖出票:7 Thread-0–卖出票:8 Thread-2–卖出票:6 Thread-2–卖出票:5 Thread-2–卖出票:4 Thread-1–卖出票:8 Thread-2–卖出票:3 Thread-0–卖出票:7 Thread-2–卖出票:2 Thread-2–卖出票:1 Thread-1–卖出票:7 Thread-0–卖出票:6 Thread-1–卖出票:6 Thread-0–卖出票:5 Thread-0–卖出票:4 Thread-1–卖出票:5 Thread-0–卖出票:3 Thread-1–卖出票:4 Thread-1–卖出票:3 Thread-1–卖出票:2 Thread-0–卖出票:2 Thread-1–卖出票:1 Thread-0–卖出票:1 如果用Runnable就可以实现资源共享,下面看例子: 1 package multithreading; 2 3 public class MyThreadWithImplements implements Runnable { 4 5 private int tickets = 10; 6 7 @Override 8 public void run() { 9 10 for (int i = 0; i <= 100; i++) { 11 if(tickets>0){ 12 System.out.println(Thread.currentThread().getName()+”–卖出票:” + tickets–); 13 } 14 } 15 } 16 17 18 public static void main(String[] args) { 19 MyThreadWithImplements myRunnable = new MyThreadWithImplements(); 20 Thread thread1 = new Thread(myRunnable, “窗口一”); 21 Thread thread2 = new Thread(myRunnable, “窗口二”); 22 Thread thread3 = new Thread(myRunnable, “窗口三”); 23 24 thread1.start(); 25 thread2.start(); 26 thread3.start(); 27 } 28 29 } 运行结果: 窗口二–卖出票:10 窗口三–卖出票:9 窗口一–卖出票:8 窗口三–卖出票:6 窗口三–卖出票:4 窗口三–卖出票:3 窗口三–卖出票:2 窗口三–卖出票:1 窗口二–卖出票:7 窗口一–卖出票:5 每个线程共享了对象myRunnable的资源,卖出的总票数是对的,但是顺序是乱的,怎么办? 同步关键词synchronized 线程执行的时候,一个个执行不就有序了。即线程1在执行的时候,其他线程阻塞不要执行。 加synchronize。 1 package multithreading.sync; 2 3 public class MyThreadWithImplements implements Runnable { 4 5 private int tickets = 10; 6 7 @Override 8 public synchronized void run() { 9 //同步关键词synchronized 10 for (int i = 0; i <= 100; i++) { 11 if(tickets>0){ 12 System.out.println(Thread.currentThread().getName()+”–卖出票:” + tickets–); 13 } 14 } 15 } 16 17 18 public static void main(String[] args) { 19 20 MyThreadWithImplements myRunnable = new MyThreadWithImplements(); 21 Thread thread1 = new Thread(myRunnable, “窗口一”); 22 Thread thread2 = new Thread(myRunnable, “窗口二”); 23 Thread thread3 = new Thread(myRunnable, “窗口三”); 24 25 thread1.start(); 26 thread2.start(); 27 thread3.start(); 28 } 29 30 } 运行结果 窗口一–卖出票:10 窗口一–卖出票:9 窗口一–卖出票:8 窗口一–卖出票:7 窗口一–卖出票:6 窗口一–卖出票:5 窗口一–卖出票:4 窗口一–卖出票:3 窗口一–卖出票:2 窗口一–卖出票:1 缺陷 1、如果这个锁的线程由于要等待IO或者其他原因(比如调用sleep方法)被阻塞了,但是又没有释放锁,其他线程便只能干巴巴地等待,这多么影响程序执行效率。 2、当有多个线程读写文件时,读写操作会发生冲突现象,写操作会发生冲突现象,但是读操作不会发生冲突现象。但是采用synchronized关键字来实现同步的话,就会导致一个问题:如果多个线程都只是进行读操作,当一个线程在进行读操作时,其他线程只能等待无法进行读操作。 因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。另外,通过Lock可以知道线程有没有成功到锁。这个是synchronized无法办到的。总的来说,也就是说Lock提供了比synchronized更多的功能。 ReadWriteLock读写文件 概述 ReadWriteLock是一个接口,在它里面只定义了两个方法:一个读的锁和一个写的锁。 读的锁:A线程了读的锁,那么B线程也可以读的锁。 写的锁:A线程了写的锁,那么B线程不能读也不能写的锁。 1 public interface ReadWriteLock { 2 / 3 * Returns the lock used for reading. 4 * 读的锁,A线程了读的锁,那么B线程也可以读的锁 5 * @return the lock used for reading. 6 */ 7 Lock readLock(); 8 9 / 10 * Returns the lock used for writing. 11 * 写的锁,A线程了写的锁,那么B线程不能读也不能写的锁。 12 * @return the lock used for writing. 13 */ 14 Lock writeLock(); 15 } 。。。未完待续
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/46752.html