Multi-Thread 1: how to use synchronized

本文探讨了Java中线程间的同步与通信机制。通过使用synchronized关键字实现线程安全,确保同一实例上的方法调用不会相互干扰。此外,文章还介绍了如何利用wait和notify方法在多个线程间进行条件通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. synchronized

If two threads are using the same function( here we use output to print out string) of another instance, if we want to make sure that these two threads are not disturbing each other.

public class TraditionalThreadSynchronize {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new TraditionalThreadSynchronize().initial();
	}
	
	private void initial(){
		final Outputter outputter = new Outputter();
		new Thread(new Runnable(){  //this is the first theread
			public void run(){
				while(true){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					outputter.output("aaaaaaaaaaa"); //the thread want to use outputer print a string.
				}
					
			}
			
		}).start();
		
		new Thread(new Runnable(){//thread two
			public void run(){
				while(true){
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					outputter.output("bbbbbbbbbbbbb");  //thread two also want to use the function to print
				}
					
			}
			
		}).start();
	}
	
	class Outputter{
		public void output(String name){
			int len = name.length();
			for(int i= 0;i<len;i++){
				System.out.print(name.charAt(i));
			}
			System.out.println();
		}
	}

}

If code won't escape disturbing each other.
The calling function must be the same one from the same instance!

 Error Example 1:

new Thread(new Runnable(){
			@Override
			public void run() {
				while(true){
					try {
						Thread.sleep(10);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					new outputer.output("bbbbbbbb");
				}
				
			}
		}).start();

if we use new outputer.output("bbbbbbbbb"), still won't work. since the two threads are calling different function from two different instance.So one thing is clear that we have to add synchronized key word and it should be added to the same Instance.

ANSWER 1:
we can make it possible by letting two threads calling for the same function, of the same Instance  so we can change the output function to:

public synchronized void output(String name){
			int len = name.length();
			for(int i=0;i<len;i++){
			<span style="white-space:pre">	</span>System.out.print(name.charAt(i));
			}
			System.out.println();
		}	
// Synchronized add to the function is the same as synchronized(this). the Instance is sychronized for this function

ANSWER 2: 
Since we already know the key point is to make the same Instance be synchronized, so we can make the two threads call fordifferent functions( output1, and output3), as long as the instance is synchronized(which is also easy to do: both of the two functions should addsynchronized key word)

public void output(String name){
	int len = name.length();
	synchronized (this) 
	{
	for(int i=0;i<len;i++){
		System.out.print(name.charAt(i));
	}
	System.out.println();
	}
}
		
public synchronized void output2(String name){
	int len = name.length();
	for(int i=0;i<len;i++){
			System.out.print(name.charAt(i));
	}
	System.out.println();
}

ANSWER 3:  in the case that the function is a static method
If the method is a static method, since static method is initialized before Instance, if we still want to synchronize two method, One way is to make both of the two methodstatic synchronized, another way, we can synchronize on the instance's class 

public void output(String name){
	int len = name.length();
	synchronized (Outputer.class) 
	{
		for(int i=0;i<len;i++){
			System.out.print(name.charAt(i));
		}
		System.out.println();
	}
}		

public synchronized void output2(String name){
	int len = name.length();
	for(int i=0;i<len;i++){
		System.out.print(name.charAt(i));
	}
	System.out.println();
}


2.Threads communicate with each other

when we have many threads working together, sometimes we need to switch between each other on some condition. such as thread1 work 5 times, then switch to thread 2 to run 10 times, then switch back to thread1 to run 5 times. On this condition, we need to design the logic, so that the thread knowns when to run, and when to wait aside and let others to run.

1. The detailed work of thread can be written to different methods into a single Class, and all these method should add Synchronized key word. So that when we Initialize the class, all the threads that want to do such work, are synchronized on one lock and will wait for their turn.

2. Condition of switching to each other should also be written into this class, so that other classes can be robust. can it's easy to maintain the code latter.

public class Business {

	boolean subFirst = true;
	public synchronized void subJob(){
		while(!subFirst){
			try {
				this.wait();  //even though get the lock, if it's not our turn, we should wait and give back the lock.
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		for(int i=0;i<10;i++){
				System.out.println("sub...."+Thread.currentThread().getName()+" is running "+(i+1));
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
		subFirst = false;
		this.notify(); // wake other waitting threads
	}
	
	public synchronized void mainjob(){
		while(subFirst){
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
		for(int i=0;i<100;i++){
			System.out.println("main*****"+Thread.currentThread().getName()+" is running "+(i+1));
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		subFirst = true;
		this.notify();
		
	}

	
}

Main class

public class TraditionalThreadCommunication {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TraditionalThreadCommunication t = new TraditionalThreadCommunication();
		Business business = new Business();
		t.startJob(business,50);

	}
	
	public void startJob(final Business business, final int cycles){
		new Thread(new Runnable(){ //sub thread run
			public void run(){
				//the detail logic should all be written into Business class
				for(int i=1; i<=cycles;i++)
					business.subJob();
			
			}
		}).start();
		
		new Thread(new Runnable(){ //main thread run
			public void run(){
				//the detail logic should be written in business class, so that the 
				//this class be robust, and can be easily changed in latter maintainance
				for(int i=1; i<=cycles;i++)
					business.mainjob();
			}
		}).start();
	}
	

}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值