线程间的数据共享

本文通过示例代码展示了使用Thread子类和Runnable接口创建线程并进行数据共享的不同方式。通过比较两种方法在出售机票场景中的表现,揭示了它们在实际应用中的差异。

线程间的数据共享可以通过两种方式

通过Thread子类创建进程的方法

通过Runnable接口实现进程之间的共享



比较这两种实现进程共享的区别


Thread子类创建进程:

package practice4;

public class ThreadSale extends Thread{
	private int tickets=10;

	public void run(){
		while(true){
			if(tickets>0)
				System.out.println(getName()+" 售机票第"+tickets--+"号");
			else
				System.exit(0);
		}
	}
}

public class App11_4 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ThreadSale t1=new ThreadSale();
		ThreadSale t2=new ThreadSale();
		ThreadSale t3=new ThreadSale();
		t1.start();
		t2.start();
		t3.start();
	}

}

运行结果:

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-2 售机票第6号
Thread-2 售机票第5号
Thread-0 售机票第8号
Thread-2 售机票第4号
Thread-2 售机票第3号
Thread-2 售机票第2号
Thread-2 售机票第1号
Thread-1 售机票第8号
Thread-1 售机票第7号
Thread-1 售机票第6号
Thread-1 售机票第5号
Thread-1 售机票第4号
Thread-1 售机票第3号
Thread-1 售机票第2号
Thread-1 售机票第1号
Thread-0 售机票第7号
Thread-0 售机票第6号
Thread-0 售机票第5号
Thread-0 售机票第4号
Thread-0 售机票第3号
Thread-0 售机票第2号


Runnable接口创建进程:


package practice4;

public class ThreadSale1 implements Runnable{
	private int tickets=10;
	
	public void run(){
		while(true){
			if(tickets>0)
				System.out.println(Thread.currentThread().getName()+"  售机票第"+tickets--+"号");
			else
				System.exit(0);
		}
	}
}


public class App11_5 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ThreadSale1 t=new ThreadSale1();
		Thread t1=new Thread(t,"第一售票窗口");
		Thread t2=new Thread(t,"第二售票窗口");
		Thread t3=new Thread(t,"第三售票窗口");
		t1.start();
		t2.start();
		t3.start();
	}

}


运行结果:

第二售票窗口  售机票第9号
第三售票窗口  售机票第8号
第一售票窗口  售机票第10号
第三售票窗口  售机票第6号
第二售票窗口  售机票第7号
第三售票窗口  售机票第4号
第一售票窗口  售机票第5号
第三售票窗口  售机票第2号
第二售票窗口  售机票第3号
第一售票窗口  售机票第1号

可以看出Runnable接口比Thread子类更加实用


在Java中,线程间共享数据是通过多个线访问同一个对象来实现的。这种方式通常涉及共享可变对象,其中多个线可以读取和修改对象的状态。然而,在多线环境中,这种共享方式可能会导致数据竞争和一致性问题,因此必须采取适当的机制来确保线安全[^2]。 一种常见的方法是使用锁机制,例如`synchronized`关键字,它可以确保多个线在访问共享数据时是互斥的。当一个线正在访问一个被`synchronized`保护的代码块或方法时,其他线必须等待,直到当前线释放锁。这种机制可以防止多个线同时修改共享数据,从而避免了数据竞争。 下面是一个使用`synchronized`关键字来确保线安全的例子: ```java public class SharedData { private int sharedVariable = 0; public synchronized void increment() { sharedVariable++; } public synchronized int getSharedVariable() { return sharedVariable; } } ``` 在这个例子中,`increment`方法和`getSharedVariable`方法都被声明为`synchronized`,这意味着同一时间只有一个线可以执行这些方法中的任何一个。这样可以确保当一个线正在修改`sharedVariable`时,另一个线不能同时读取或修改它,从而保证了数据的一致性和完整性[^2]。 除了使用`synchronized`关键字之外,还可以使用`java.util.concurrent`包提供的高级并发工具,如`ReentrantLock`、`Semaphore`、`CountDownLatch`等,它们提供了比内置锁更灵活的锁定机制,并且支持尝试锁定、超时等特性。 此外,Java还提供了`volatile`关键字,它可以用来修饰变量,确保变量的读写操作是原子性的,并且对所有线可见。这对于某些特定的场景非常有用,比如状态标志或者简单的计数器。 最后,还可以使用线局部变量(`ThreadLocal`)来为每个线提供独立的变量副本,这样每个线都可以独立地改变自己的副本而不会影响到其他线使用的副本。这种方法适用于那些不需要跨线共享数据。 总之,在Java中实现线程间安全地共享数据需要考虑使用适当的同步机制来保证数据的一致性和线的安全性。根据具体的应用场景,可以选择不同的技术和策略来达到这一目的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值