runnable的共享数据

Java实现多线程,有两个方法,实现runable接口和继承Thread

1.实现Runnable接口

使用同一个runnable构造的不同线程之间是可以共享数据的

class MyThread extends Thread {
	private int share = 10;

	@Override
	public void run() {
		if (share > 0) {
			System.out.println(share--);
		}
	}
}
	MyRunnable mr = new MyRunnable();
	new Thread(mr).start();
	new Thread(mr).start();
	new Thread(mr).start();

结果

10

9

8


2.继承Thread

class MyThread extends Thread {
	private int share = 10;

	@Override
	public void run() {
		if (share > 0) {
			System.out.println(share--);
		}
	}
}
	MyThread mt = new MyThread();
	mt.start();
	mt = new MyThread();
	mt.start();
	mt = new MyThread();
	mt.start();

结果

10

10

10

不同的线程之间不能共享数据。


### Java 线程间数据共享的方法 #### 使用 `synchronized` 关键字 `synchronized` 是一种用于控制多个线程对共享资源访问的关键字。当一个方法被声明为同步时,意味着同一时刻只有一个线程能够执行该方法中的代码[^4]。 对于非静态同步方法而言,多线程间共享的是调用该方法的对象;而对于静态同步方法来说,则是所有线程共同分享调用了此方法的类本身。这种方式适用于需要保护特定对象或整个类级别的操作场景下实现线程间的通信和协调工作。 ```java public class Counter { private int count; public synchronized void increment() { // 非静态同步方法 this.count++; } public static synchronized void reset(Counter counter) { // 静态同步方法 counter.count = 0; } } ``` #### 利用公共可变对象作为参数传递给各个线程 通过让不同线程持有相同的 `Runnable` 实现体来达到目的,在此类中封装好待处理的任务逻辑以及想要在线程之间交换的信息即可完成简单的交互过程[^5]。 例如在一个售票系统里边,我们可以把表示剩余票数的那个整数值放在实现了 `Runnable` 接口的一个类里面去管理: ```java class TicketSeller implements Runnable { private final Object lock = new Object(); private int ticketsLeft = 100; @Override public void run(){ while(true){ sellTicket(); } } private void sellTicket(){ synchronized(lock){ // 加锁确保每次只允许一个线程修改ticketsLeft if(ticketsLeft>0){ System.out.println(Thread.currentThread().getName()+" sold a ticket, "+ (--ticketsLeft)+" left."); }else{ break; } } } } ``` #### 运用高级并发集合类库 Java 提供了一些专门设计用来简化并行程序编写难度的数据结构,比如阻塞队列(`BlockingQueue`)、原子变量(`AtomicInteger`, `AtomicLong`等),这些组件内部已经做好了必要的同步措施,开发者只需要按照API文档说明正常使用就能保证良好的性能表现的同时也解决了潜在的竞争条件问题。 - **阻塞队列**:适合生产者消费者模式下的消息传输机制; - **原子类型**:提供了一套高效无锁算法实现的基础运算功能,可用于计数器统计等方面的应用场合。 ```java import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; // 创建固定容量大小为10的双端链表形式的阻塞队列 BlockingQueue<String> queue = new LinkedBlockingDeque<>(10); queue.put("item"); // 向队尾添加元素(必要时等待空间) String item = queue.take(); // 从队首取出元素(必要时等待有可用项) import java.util.concurrent.atomic.AtomicInteger; AtomicInteger atomicInt = new AtomicInteger(0); atomicInt.incrementAndGet(); // 原子增加返回更新后的值 int currentValue = atomicInt.get(); // 获取当前值 ``` #### ThreadLocal 方式 `ThreadLocal` 能够使得每个使用它的线程都拥有独立的一份副本,这样就避免了由于直接暴露全局/成员属性所带来的竞态风险。通常情况下我们会将那些频繁读写却不需要跨线程传播的状态量交给它来维护,如用户的登录凭证信息或者其他临时性的上下文环境设置等等[^3]。 ```java private static final ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0); void setThreadLocalData(int value){ threadLocalValue.set(value); } int getThreadLocalData(){ return threadLocalValue.get(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值