Java Runnable接口与synchronized关键字(同步方法)

简介: 本文目录1. 概述2. 简单的Runnable接口实现多线程例子3. 利用synchronized实现同步

1. 概述

通过Runable接口实现多线程比继承Thread接口要更实用一些,起码不会占用单继承的名额。

在实现多线程时,还是需要注意同步的问题,下面一个具体的例子。

2. 简单的Runnable接口实现多线程例子

本例子模拟了访客访问网站这个事情。

package org.maoge.thread;
//通过Runnable接口实现多线程
public class RunnableDemo implements Runnable{
  private int count=0;//系统访问次数
  @Override
  public void run() {
    count++;
    System.out.println("第"+count+"位访客来啦!");
  }
  public static void main(String[] args) {
    RunnableDemo rd=new RunnableDemo();
    for(int i=0;i<50;i++){
      Thread thread=new Thread(rd);
      thread.start();//一定要注意不是通过.run()启动线程
    }
  }
}

输出如下,有两个问题:1是顺序不对,2是重复(比如第21位访客来啦出现了2次)。

第1位访客来啦!
第33位访客来啦!
第37位访客来啦!
第32位访客来啦!
第38位访客来啦!
第39位访客来啦!
第41位访客来啦!
第43位访客来啦!
第44位访客来啦!
第46位访客来啦!
第31位访客来啦!
第30位访客来啦!
第49位访客来啦!
第29位访客来啦!
第28位访客来啦!
第27位访客来啦!
第26位访客来啦!
第25位访客来啦!
第24位访客来啦!
第23位访客来啦!
第22位访客来啦!
第21位访客来啦!
第21位访客来啦!
第19位访客来啦!
第18位访客来啦!
第17位访客来啦!
第16位访客来啦!
第15位访客来啦!
第14位访客来啦!
第13位访客来啦!
第12位访客来啦!
第11位访客来啦!
第11位访客来啦!
第9位访客来啦!
第8位访客来啦!
第7位访客来啦!
第6位访客来啦!
第5位访客来啦!
第4位访客来啦!
第3位访客来啦!
第2位访客来啦!
第49位访客来啦!
第48位访客来啦!
第48位访客来啦!
第45位访客来啦!
第42位访客来啦!
第40位访客来啦!
第36位访客来啦!
第35位访客来啦!
第34位访客来啦!

简单分析下:

1,顺序不对,这个非常好理解,发起线程后,每个线程都是相对独立的,执行run()方法跟很多因素相关,我们无从分析哪个会执行的快、哪个会慢,所以当然会出现不按顺序的情况。


2,第21位访客,输出了2次。是这样的count=21的机会肯定只有一次,

假设有两个线程a和b,a执行完成后count=20,然后尚未执行输出,此时b线程执行了 count++后count=21,然后此时a、b的输出发生在另外一个线程count++之前,所以发生了重复输出。


3. 利用synchronized实现同步

我们当然是想告诉游客正确的访问次序,所以可以加上synchronized关键字,将run()方法改为同步方法,这样就锁定了这个方法(当一个线程访问时,别的线程不能访问,一个一个来,是以所谓同步)。


代码如下:

package org.maoge.thread;
//通过Runnable接口实现多线程
public class RunnableDemo implements Runnable{
  private int count=0;//系统访问次数
  @Override
  public synchronized void run() {//通过synchronized实现同步
    count++;
    System.out.println("第"+count+"位访客来啦!");
  }
  public static void main(String[] args) {
    RunnableDemo rd=new RunnableDemo();
    for(int i=0;i<50;i++){
      Thread thread=new Thread(rd);
      thread.start();//一定要注意不是通过.run()启动线程
    }
  }
}

输出如下,可见是我们要的结果:

第1位访客来啦!
第2位访客来啦!
第3位访客来啦!
第4位访客来啦!
第5位访客来啦!
第6位访客来啦!
第7位访客来啦!
第8位访客来啦!
第9位访客来啦!
第10位访客来啦!
第11位访客来啦!
第12位访客来啦!
第13位访客来啦!
第14位访客来啦!
第15位访客来啦!
第16位访客来啦!
第17位访客来啦!
第18位访客来啦!
第19位访客来啦!
第20位访客来啦!
第21位访客来啦!
第22位访客来啦!
第23位访客来啦!
第24位访客来啦!
第25位访客来啦!
第26位访客来啦!
第27位访客来啦!
第28位访客来啦!
第29位访客来啦!
第30位访客来啦!
第31位访客来啦!
第32位访客来啦!
第33位访客来啦!
第34位访客来啦!
第35位访客来啦!
第36位访客来啦!
第37位访客来啦!
第38位访客来啦!
第39位访客来啦!
第40位访客来啦!
第41位访客来啦!
第42位访客来啦!
第43位访客来啦!
第44位访客来啦!
第45位访客来啦!
第46位访客来啦!
第47位访客来啦!
第48位访客来啦!
第49位访客来啦!
第50位访客来啦!


相关文章
|
2月前
|
Java
Java语言实现字母大小写转换的方法
Java提供了多种灵活的方法来处理字符串中的字母大小写转换。根据具体需求,可以选择适合的方法来实现。在大多数情况下,使用 String类或 Character类的方法已经足够。但是,在需要更复杂的逻辑或处理非常规字符集时,可以通过字符流或手动遍历字符串来实现更精细的控制。
251 18
|
2月前
|
Java 编译器 Go
【Java】(5)方法的概念、方法的调用、方法重载、构造方法的创建
Java方法是语句的集合,它们在一起执行一个功能。方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中被创建,在其他地方被引用方法的优点使程序变得更简短而清晰。有利于程序维护。可以提高程序开发的效率。提高了代码的重用性。方法的名字的第一个单词应以小写字母作为开头,后面的单词则用大写字母开头写,不使用连接符。例如:addPerson。这种就属于驼峰写法下划线可能出现在 JUnit 测试方法名称中用以分隔名称的逻辑组件。
205 4
|
3月前
|
算法 安全 Java
除了类,Java中的接口和方法也可以使用泛型吗?
除了类,Java中的接口和方法也可以使用泛型吗?
154 11
|
2月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
313 5
|
缓存 安全 Java
《volatile使用与学习总结:》多层面分析学习java关键字--volatile
《volatile使用与学习总结:》多层面分析学习java关键字--volatile
135 0
|
安全 Java 编译器
Java多线程基础-6:线程安全问题及解决措施,synchronized关键字与volatile关键字(一)
线程安全问题是多线程编程中最典型的一类问题之一。如果多线程环境下代码运行的结果是符合我们预期的,即该结果正是在单线程环境中应该出现的结果,则说这个程序是线程安全的。 通俗来说,线程不安全指的就是某一代码在多线程环境下执行会出现bug,而在单线程环境下执行就不会。线程安全问题本质上是由于线程之间的调度顺序的不确定性,正是这样的不确定性,给我们的代码带来了很多“变数”。 本文将对Java多线程编程中,线程安全问题展开详细的讲解。
258 0
|
存储 安全 Java
【亮剑】Java并发编程涉及`ThreadLocal`、`Volatile`、`Synchronized`和`Atomic`四个关键机制
【4月更文挑战第30天】Java并发编程涉及`ThreadLocal`、`Volatile`、`Synchronized`和`Atomic`四个关键机制。`ThreadLocal`为每个线程提供独立变量副本;`Volatile`确保变量可见性,但不保证原子性;`Synchronized`实现同步锁,保证单线程执行;`Atomic`类利用CAS实现无锁并发控制。理解其原理有助于编写高效线程安全代码。根据业务场景选择合适机制至关重要。
129 0
|
存储 缓存 Java
Java中不可或缺的关键字「volatile」
Java中不可或缺的关键字「volatile」
378 0
|
缓存 安全 Java
Java并发编程中的四个关键字:ThreadLocal、Volatile、Synchronized和Atomic
Java并发编程中的四个关键字:ThreadLocal、Volatile、Synchronized和Atomic
364 0
|
缓存 安全 Java
Java 关键字特性增强-Volatile
Java高级特性增强-Volatile volatile关键字 volatile特性
220 0
Java 关键字特性增强-Volatile