java多线程实战( 多个线程 修改同一个变量)

java多线程实战( 多个线程 修改同一个变量)  synchronized 同步


介绍

java多线程实战

需求

创建两个线程,分别输出“a”,“b”,要求输出总和为30个。

线程介绍

一、定义线程
1、扩展java.lang.Thread类。
此类中有个run()方法,应该注意其用法:
public void run()
如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回。
Thread 的子类应该重写该方法。
2、实现java.lang.Runnable接口。
void run()
使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线程中调用对象的 run 方法。
方法 run 的常规协定是,它可能执行任何所需的操作。
二、实例化线程
1、如果是扩展java.lang.Thread类的线程,则直接new即可。
2、如果是实现了java.lang.Runnable接口的类,则用Thread的构造方法:
Thread(Runnable target) 
Thread(Runnable target, String name) 
Thread(ThreadGroup group, Runnable target) 
Thread(ThreadGroup group, Runnable target, String name) 
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
 
三、启动线程
在线程的Thread对象上调用start()方法,而不是run()或者别的方法。
在调用start()方法之前:线程处于新状态中,新状态指有一个Thread对象,但还没有一个真正的线程。
在调用start()方法之后:发生了一系列复杂的事情
启动新的执行线程(具有新的调用栈);
该线程从新状态转移到可运行状态;
当该线程获得机会执行时,其目标run()方法将运行。
注意:对Java来说,run()方法没有任何特别之处。像main()方法一样,它只是新线程知道调用的方法名称(和签名)。因此,在Runnable上或者Thread上调用run方法是合法的。但并不启动新的线程。

功能实现


package com.thread;

public class ThreadTest {
	public int i=0;//计数器
	public static final int MAX=30;//总次数
	public static void main(String args[])
	{
		ThreadTest t = new ThreadTest();
		Thread thread1 = new Thread(new MeThead(t,0));
		Thread thread2 = new Thread(new MeThead(t,1));
		thread1.start();
		thread2.start();
	}
	/**
	 * 需要考虑变量i的同步问题。
	 * @return
	 */
	
	public <span style="color:#ff6666;">synchronized</span> boolean printA()
	{
		if(i<MAX)
		{
			System.out.print(i+"a");
			i++;
			return true;
		}
		return false;
		
	}
	/**
	 * 需要考虑变量i的同步问题。
	 * @return
	 */
	public <span style="color:#ff6666;">synchronized</span> boolean printB()
	{
		if(i<MAX)
		{
		System.out.print(i+"b");
		i++;
		return true;
		}
		return false;

	}
}

class MeThead implements Runnable{
	ThreadTest t;
	int method=0;
	public MeThead(ThreadTest t,int method)
	{
		this.t=t;
		this.method=method;
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		
		while(1==1)
		{
			boolean flag =false;
			if(method==0)
			{
				flag = t.printA();
				
			}
			else if(method==1)
			{
				flag = t.printB();
			}
			//如果结束了,则退出循环
			if(flag==false)
			{
				break;
			}
		}
		
	}
	
	
}

注意点:
1.需要考虑同一个变量的同步的问题!对同一个变量的操作,必须要放入到同步方法内。否则取到的变量值会不一致!
举个例子,如果thread里面的run方法是如下实现,则就会出现变量的值不一致问题!
比如第一次,i=0,那么thread1和thread2同时进入了while循环内,thread1执行了printA方法,thread2则等待thread1释放资源。可能thread1执行了30次,最后i=30之后thread1执行完成。这时候,thread2还在等待中,发现资源已经可以使用了,则调用了printB的方法。最后就会出现打印了31次的情况!
这个需要注意的。不然很容易搞错。

如下是错误的程序:
<span style="color:#333333;"></span>package com.thread;


public class ThreadTest {
<span style="white-space:pre">	</span>public static void main(String args[])
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>ThreadTest t = new ThreadTest();
<span style="white-space:pre">		</span>Thread thread1 = new Thread(new MeThead(t,0));
<span style="white-space:pre">		</span>Thread thread2 = new Thread(new MeThead(t,1));
<span style="white-space:pre">		</span>thread1.start();
<span style="white-space:pre">		</span>thread2.start();
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>public synchronized void printA()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>System.out.print(Param.i+"a");
<span style="white-space:pre">		</span>Param.i++;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>public synchronized void printB()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>System.out.print(Param.i+"b");
<span style="white-space:pre">		</span>Param.i++;


<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>
}
/**
 * 设置成全局静态变量。
 * @author hbx
 *
 */
class Param{
<span style="white-space:pre">	</span>public static  int i=0;//两个线程每打印一次,i进行自增一次,跟MAX比较,只要小于MAX,则一直打印
<span style="white-space:pre">	</span>public static final int MAX=20;
<span style="white-space:pre">	</span>
}
class MeThead implements Runnable{
<span style="white-space:pre">	</span>ThreadTest t;
<span style="white-space:pre">	</span>int method=0;
<span style="white-space:pre">	</span>public MeThead(ThreadTest t,int method)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>this.t=t;
<span style="white-space:pre">		</span>this.method=method;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>@Override
<span style="white-space:pre">	</span>public void run() {
<span style="white-space:pre">		</span>// TODO Auto-generated method stub
<span style="white-space:pre">		</span>
<span style="white-space:pre">		</span><span style="color:#ff6666;">while(Param.i<Param.MAX)</span>
<span style="white-space:pre">		</span>{
<span style="white-space:pre">			</span>
<span style="white-space:pre">			</span>if(method==0)
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>//System.out.println("-"+Param.i+"a-");
<span style="white-space:pre">				</span><span style="color:#ff6666;">t.printA();</span>
<span style="white-space:pre">			</span>}
<span style="white-space:pre">			</span>else if(method==1)
<span style="white-space:pre">			</span>{
<span style="white-space:pre">				</span>//System.out.println("-"+Param.i+"b-");


<span style="white-space:pre">				</span><span style="color:#ff6666;">t.printB()</span>;
<span style="white-space:pre">			</span>}
<span style="white-space:pre">		</span>}
<span style="white-space:pre">		</span>
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>
}<span style="color:#333333;"></span>





  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值