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 } 

。。。未完待续

原文地址:https://www.cnblogs.com/superslow/p/9010639.html

时间: 2024-07-29 22:51:00

JAVA多线程 & 同步关键词synchronized & ReadWriteLock读写文件的相关文章

java多线程——同步块synchronized详解

Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免竞争.本文介绍以下内容: Java同步关键字(synchronzied) 实例方法同步 静态方法同步 实例方法中同步块 静态方法中同步块 Java同步示例 Java 同步关键字(synchronized) Java中的同步块用synchronized标记.同步块在Java中是同步在某个对象上.所有同步在一个对象上的同步块在同时只能被一个线程进入并执行操作.所有其他等待进入该同步块的线程将

Java多线程-同步:synchronized 和线程通信:生产者消费者模式

大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同步:synchronized 多个线程同时访问一个对象,可能造成非线程安全,数据可能错误,所谓同步:就是控制多个线程同时访就是控制多线程操作同一个对象时,注意是同一个对象,数据的准确性, 确保数据安全,但是加入同步后因为需要等待,所以效率相对低下. 如:一个苹果,自己一个人去咬怎么都不会出问题,但是

转:关于JAVA多线程同步

转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖于若干方法和关键字.将心得记录如下: 1  wait方法:        该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态

java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定.假设我们事先不知道同步函数用的是什么锁:如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题. 看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不

Java线程同步(synchronized)——卖票问题

卖票问题通常被用来举例说明线程同步问题,在Java中,采用关键字synchronized关键字来解决线程同步的问题. Java任意类型的对象都有一个标志位,该标志位具有0,1两种状态,其开始状态为1,当某个线程执行了synchronized(object)语句后,object对象的标志位变为0状态,直到执行完整个synchronized语句中的代码块后,该对象的标志位又回到1状态. 当一个线程执行到synchronized(object)语句的时候,先检查object对象的标志位,如果为0状态,

Java多线程同步 synchronized 关键字的使用

代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D)运行完这个方法后再运行此线程A,没有的话,直接运行它包括两种用法:synchronized 方法和 synchronized 块. JAVA多线程买票案例 synchronized 同步 用synchronized 块实现同步 public static void main(String[] args) { // runable对

(转) Java多线程同步与异步

Java线程 同步与异步 线程池1)多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,A线程修改了B线 程的处理的数据,而B线程又修改了A线程处理的数理.显然这是由于全局资源造成的,有时为了解 决此问题,优先考虑使用局部变量,退而求其次使用同步代码块,出于这样的安全考虑就必须牺牲 系统处理性能,加在多线程并发时资源挣夺最激烈的地方,这就实现了线程的同步机制 同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求 不到,怎么办,A线程只能等待下去

Java多线程---同步与锁

一,线程的同步是为了防止多个线程访问一个数据对象时,对数据造成的破坏. 二.同步和锁定 1.锁的原理 Java中每个对象都有一个内置锁. 当程序运行到非静态的synchronized同步方法上时,自动获得与正在执行代码类的当前实例(this实例)有关的锁.获得一个对象的锁也称为获取锁.锁定对象.在对象上锁定或在对象上同步. 当程序运行到synchronized同步方法或代码块时该对象锁才起作用. 一个对象只有一个锁.所以,如果一个线程获得该锁,就没有其他线程可以获得锁,直到第一个线程释放(或返回

Java多线程之二(Synchronized)

常用API method 注释 run() run()方法是我们创建线程时必须要实现的方法,但是实际上该方法只是一个普通方法,直接调用并没有开启线程的作用. start() start()方法作用为使该线程开始执行:Java虚拟机调用该线程的 run 方法. 但是该方法只能调用一次,如果线程已经启动将会抛出IllegalThreadStateException异常. yield() yield()方法让出CPU并且不会释放锁,让当前线程变为可运行状态,所以CPU下一次选择的线程仍可能是当前线程.