在多线程的使用中往往需要多个线程对一个共享数据进行操作,这时就会出现线程安全问题,得到的数据可能会重复,错误,那么可以使用以下的三种方法解决:
同步代码块Synchronized
将你操作共享数据的代码放入Synchronized(){}中
继承Thread
代码:
class MyThreadSynchronized extends Thread{
//共享数据
private static int count=100;
@Override
public void run() {
while (true){
synchronized (MyThreadSynchronized.class){
if(count>0){
System.out.println(Thread.currentThread().getName() + ":第" + count + "个");
count--;
}else{
break;
}
}
}
}
}
public class ThreadExtendsSynchronized {
public static void main(String[] args) {
MyThreadSynchronized myThreadSynchronized1=new MyThreadSynchronized();
MyThreadSynchronized myThreadSynchronized2=new MyThreadSynchronized();
myThreadSynchronized1.setName("线程一");
myThreadSynchronized2.setName("线程二");
myThreadSynchronized1.start();
myThreadSynchronized2.start();
}
}
在继承Thread创建多线程中,需要将共享数据设置为静态(唯一),同时Synchronized的同步监视器不能写成this,因为在main中创建了多个“MyThreadSynchronized”的对象,因此写成" 此类名.class"。
实现Runnable
代码:
class MyRunnableSynchronized implements Runnable{
private int count=100;
public void run() {
while(true){
synchronized (this) {
if(count>0){
System.out.println(Thread.currentThread().getName() + ":第" + count +"个");
count--;
}else{
break;
}
}
}
}
}
public class ThreadRunnableSynchronized {
public static void main(String[] args) {
MyRunnableSynchronized myRunnableSynchronized = new MyRunnableSynchronized();
Thread thread1 = new Thread(myRunnableSynchronized);
Thread thread2 = new Thread(myRunnableSynchronized);
thread1.setName("线程一");
thread2.setName("线程二");
thread1.start();
thread2.start();
}
}
在实现Runnable创建多线程中则没有继承中的那些问题,在main中只需创建一个类对象,同步监视器也只需用this就行。
同步方法
将操作共享数据的代码放入同步方法中
继承Thread
代码
class MyThreadExtends2 extends Thread{
private static int count=100;
@Override
public void run() {
while (true){
a();
if(count<=0){
break;
}
}
}
//用static保证每一个此类的对象都使用这个方法
public static synchronized void a(){
if(count>0){
System.out.println(Thread.currentThread().getName() + ":第" + count + "个");
count--;
}
}
}
public class ThreadExtendsSynchronized2 {
public static void main(String[] args) {
MyThreadExtends2 myThreadExtends21=new MyThreadExtends2();
MyThreadExtends2 myThreadExtends22=new MyThreadExtends2();
myThreadExtends21.setName("线程一");
myThreadExtends22.setName("线程二");
myThreadExtends21.start();
myThreadExtends22.start();
}
}
同样的在继承中也需要将共享数据定义为静态
实现Runnable创建多线程
代码:
class MyThreadRunnable2 implements Runnable{
private int count=100;
public void run() {
while(true){
a();
if(count<=0){
break;
}
}
}
public synchronized void a(){
if(count>0){
System.out.println(Thread.currentThread().getName() + ":第" + count +"个");
count--;
}
}
}
public class ThreadRunnableSynchronized2 {
public static void main(String[] args) {
MyThreadRunnable2 myThreadRunnable2=new MyThreadRunnable2();
Thread thread1=new Thread(myThreadRunnable2);
Thread thread2=new Thread(myThreadRunnable2);
thread1.setName("线程一");
thread2.setName("线程二");
thread1.start();
thread2.start();
}
}
使用ReentrantLock
实现Runnable创建多线程(继承方法差不多)
代码:
class MyThreadReentrantLock implements Runnable{
private int count=100;
//创建ReentrantLock的对象
ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
while(true){
try{
//加“锁”
lock.lock();
if(count>0){
System.out.println(Thread.currentThread().getName() + ":第" + count + "个");
count--;
}else{
break;
}
}finally {
//解“锁”
lock.unlock();
}
}
}
}
public class ThreadRunnableLock {
public static void main(String[] args) {
MyThreadReentrantLock myThreadReentrantLock=new MyThreadReentrantLock();
Thread thread1=new Thread(myThreadReentrantLock);
Thread thread2=new Thread(myThreadReentrantLock);
thread1.setName("线程一");
thread2.setName("线程二");
thread1.start();
thread2.start();
}
}
ReentrantLock类中的lock()和 unlock()需将代码写在try语句块中(无需添加catch语句块) finally语句块中写unlock()。