`
clq9761
  • 浏览: 587979 次
  • 性别: Icon_minigender_1
  • 来自: 福建
社区版块
存档分类
最新评论

JAVA多线程事例参考(一)

阅读更多

一. Java多线程安全问题,模拟银行存款

/**
 * 
 *银行账户对象,存取款操作
 *
 */
public class Account {
	String name;
    float amount;        
    public Account(String name, float amount) {
        this.name = name;
        this.amount = amount;
    }
    // 存款
    public  void deposit(float amt) {
        float tmp = amount;
        tmp += amt;        
        try {
            Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等
        } catch (InterruptedException e) {
            // ignore
        }        
        amount = tmp;
    }
    // 取款
    public  void withdraw(float amt) {
        float tmp = amount;
        tmp -= amt;
        try {
            Thread.sleep(100);//模拟其它处理所需要的时间,比如刷新数据库等
        } catch (InterruptedException e) {
            // ignore
        } 
        amount = tmp;
    }
    public float getBalance() {
        return amount;
    }
}

 

/**
 * 
 * 多线程模拟银行存取款,如果没有采取同步,就会出现多线程安全问题,
 * 则最终的银行账户会出现金额不一致的情况。
 *
 */
public class AccountTest {

	private static int NUM_OF_THREAD = 1000;
    static Thread[] threads = new Thread[NUM_OF_THREAD];
    
    public static void main(String[] args){
        final Account acc = new Account("John", 1000.0f);
        for (int i = 0; i< NUM_OF_THREAD; i++) {
            threads[i] = new Thread(new Runnable() {
                public void run() {
                        acc.deposit(100.0f);
                        acc.withdraw(100.0f);
                }
            });
            threads[i].start();
        }

        for (int i=0; i<NUM_OF_THREAD; i++){
            try {
                threads[i].join(); //等待所有线程运行结束
            } catch (InterruptedException e) {
                // ignore
            }
        }
        System.out.println("Finally, John's balance is:" + acc.getBalance());
    }
}

 

二、Java多线程之synchronized

/**
 * 
 * synchronized中同步的对象必须是多线程中访问的同一个对象,否则达不到同步效果,
 * 也可用synchronized(this)代表当前对象。
 * 如果为synchronized(name)则达不到同步效果。
 *
 */
public class Foo extends Thread {
	private int val;	
	// 通过对公共对象静态变量加锁
	private static Object lock = new Object();
	public Foo(int v) {
		val = v;
	}	
	// 交叉输出(1,3)
	public synchronized void printVal1(int v) {
			while(true){
				System.out.println(v);
			}
	}	
	// 类同步,实现printVal是断面,输出只能是1或者只能是3而不能是两者同时出现
	public void printVal2(int v) 
	{ 
		synchronized(Foo.class) {
			while(true){
				System.out.println(v);
			}
		} 
	} 	
	// 同步的一般原理是应该尽量减小同步的粒度以到达更好的性能,比类同步(printVal2)效果更忧
	public void printVal3(int v) 
	{ 
		synchronized(lock) {
			while(true){
				System.out.println(v);
			}
		} 
	}	
	public void run() {
//		printVal1(val);
//		printVal2(val);
		printVal3(val);
	}
}

 

public class FooTest {	
	public static void main(String args[]){
		Foo f1 = new Foo(1); 
		f1.start(); 
		Foo f2 = new Foo(3);
		f2.start(); 
	}
}

 

三. Java多线程之ThreadLocal

   事例一:

/**
 * 
 *在Java的多线程编程中,为保证多个线程对共享变量的安全访问,通常会使用synchronized来保证同一时刻
 *只有一个线程对共享变量进行操作。但在有些情况下,synchronized不能保证多线程对共享变量的正确读写。
 *对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”
 *的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,
 *因此可以同时访问而互不影响。
 */
public class QuerySvc {

	private String sql;
	private static ThreadLocal<String> sqlHolder = new ThreadLocal<String>();

	public QuerySvc() {
	}	
	
	/**
	 * 从运行结果可以看出sql变量中值不能保证在execute中值和set设置的值一样, 在web应用中就表现
	 * 为一个用户查询的结果不是自己的查询条件返回的结果,而是另一个用户查询条件的结果;	 
	 * 而ThreadLocal中的值总是和set中设置的值一样,这样通过使用ThreadLocal获得了线程安全性。 
	 */	
	public void execute() {
		System.out.println("Thread " + Thread.currentThread().getId()
				+ " Sql is " + sql);
		System.out.println("Thread " + Thread.currentThread().getId()
				+ " Thread Local variable Sql is " + sqlHolder.get());
	}
	public String getSql() {
		return sql;
	}
	public void setSql(String sql) {
		this.sql = sql;
		sqlHolder.set(sql);
	}
	
	private static class Work extends Thread{		
		private QuerySvc querySvc;		
		private String sql;		
		public Work(QuerySvc querySvc,String sql){
			this.querySvc = querySvc;
			this.sql = sql;
		}		
		 public void run() {
			 querySvc.setSql(sql);
			 querySvc.execute();
		 }
	}	
	public static void main(String args[]){		
		QuerySvc  querySrc = new QuerySvc();		
		for(int k=0;k<10;k++){
			String sql = "Select * from table where id =" + k;
			new Work(querySrc,sql).start();
		}		
	}		
}

 

   事例二:

 

/**
 * 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
 * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
 * 如果要保存多个线程变量,可定义多个ThreadLocal变量,
 * 或者将多个变量封装到一个对象中,将整个对象保存到ThreadLocal变量。
 *
 */
public class SequenceNumber {	
	private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){
		public Integer initialValue(){
			return 0;
		}
	};	
	public Integer getNextNum(){
		seqNum.set(seqNum.get()+1);
		return seqNum.get();
	}
	
	// 测试方法
	public static void main(String args[]){
		SequenceNumber sn = new SequenceNumber();
		// 3个线程共享sn,各自产生序列号 
		TestClient t1 = new TestClient(sn); 
		TestClient t2 = new TestClient(sn); 
		TestClient t3 = new TestClient(sn); 
		t1.start(); 
		t2.start(); 
		t3.start();
	}
	
	// 内部静态线程类
	private static class TestClient extends Thread{
		private SequenceNumber sn; 
		public TestClient(SequenceNumber sn) { 
			this. sn = sn; 
		} 
		public void run() 
		{ 
			//每个线程打出3个序列值 
			for (int i = 0; i < 3; i++) {
				System.out.println("thread["+Thread.currentThread().getName()+ 
				"] sn["+sn.getNextNum()+"]"); 
			}
		}
	}
}

 

 

分享到:
评论

相关推荐

    JAVA多线程的实例

    描述java多线程的例子,可供进一步学习多线程的人参考

    Java多线程编程实例

    这是Java多线程编程实例一书的全部随书源码,这本书是很早的JAVA多线程编程指导书,虽然很老但是很经典,直到现在还很热,很有参考价值。

    java 多线程实例

    java 多线程实例,多线程参考资料!

    java多线程实例 源码

    java多线程实例 简单的实现机制 源码参考 自己写的

    java多线程编程实战指南 核心篇 代码

    《Java多线程编程实战指南(核心篇)》以基本概念、原理与方法为主线,辅以丰富的实战案例和生活化实例,并从Java虚拟机、操作系统和硬件多个层次与角度出发,循序渐进、系统地介绍Java平台下的多线程编程核心技术及...

    java多线程设计模式详解(PDF及源码)

    (注意,本资源附带书中源代码可供参考) 多线程与并发处理是程序设计好坏优劣的重要课题,本书通过浅显易懂的文字与实例来介绍Java线程相关的设计模式概念,并且通过实际的Java程序范例和 UML图示来一一解说,书中...

    Java多线程实例

    本文给大家介绍java多线程实例,对java多线程知识感兴趣的朋友参考下吧

    java 多线程下载实例

    java 多线程下载实例,供需要参考的童鞋学习。

    java线程简单实例.txt

    java Runnable线程简单实例。简单实用,可用可参考;多用多理解;线程可用用在很多场景,java程序猿必备技能

    一个JAVA多线程实例

    一个线程实例,可以下载下来参考参考,方便学习进步嘛!

    Java多线程下载 实例

    用Java编写的多线程下载 实例,Myeclipse中完整工程。 需要的朋友可以参考一下!

    java多线程编程实例

    主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下。

    Java多线程并发执行demo代码实例

    主要介绍了Java多线程并发执行demo代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    JAVA 多线程爬虫实例详解

    主要介绍了JAVA 多线程爬虫实例详解的相关资料,需要的朋友可以参考下

    Java多线程 实例解析

    主要介绍了Java多线程 实例解析,需要的朋友可以参考下

    JAVA多线程GUI绘图应用实例 风扇控制

    大学学习Java的时候做的一个作业,JAVA多线程和C++中的使用方法有所不同,花了很久才作出这个DEMO,不过,从此以后,就可以编写大规模JAVA程序了,希望是入门学习的一个好的参考。

    java多线程结合界面开发实例(原创)财务管理系统源代码和效果图[参考].pdf

    java多线程结合界面开发实例(原创)财务管理系统源代码和效果图[参考].pdf

    JAVA多线程编程实例详解

    主要介绍了JAVA多线程编程,结合实例形式总结分析了多线程、锁、线程池等相关原理及使用技巧,需要的朋友可以参考下

    JAVA多线程运用

    编写程序创建Storage类的实例,并创建一个Counter对象和Printer对象操作此实例。 实验步骤: (1)、创建三个类Counter, Printer,Storage (2)、创建TestCounter类,在该类中定义main函数,在main函数中定义Storage...

    Java多线程下载文件实例详解

    主要为大家详细介绍了Java多线程下载文件的实例代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

Global site tag (gtag.js) - Google Analytics