java多线程的共享变量访问控制实例
来源:互联网 发布:深圳软件停车系统 编辑:程序博客网 时间:2024/06/07 14:27
最近打算去一家电商公司,对于高并发的数据访问控制有着严格的要求,近期打算把多线程的知识在好好补一下。
线程调度有五个状态;
开始,可运行,运行,阻塞,死亡。
启动线程有两种方法。继承Thread类或则实现Runnable接口,其实Thread类也实现了Runnbale接口并实现了接口中唯一的方法run。但是Thread实例只能启动一次,无法共享变量,因此Runnable的灵活性更高。Thread(Runnable target)可以去执行Runnable实例的run方法。虽然start方法和run方法执行的内容一样但是本质是不同的,run方法只是单纯的调用而已并没有启动多线程,而start方法可以启动多线程。去查看jdk源码可以发现start有本地native修饰符,这会调用系统函数,优化执行效率。
可运行是一个线程池,对于JVM一般是从线程池里选择优先级高的线程抢占式执行,如果优先级都一样,那就看谁运气好抢到CPU资源。一般可以自己设置优先级0~10。这里还有用户线程和守护线程,JVM实例会在用户线程结束时退出,而不会等待守护线程。
运行态即开始执行该实例的run方法。为了减缓执行可以采用线程Thread.sleep(休眠的毫秒数)去给其他线程执行机会,但sleep不会放弃对象的锁,要放弃锁可以调用超类的wait(放弃毫秒数)方法。notify和notifyAll也可以去唤醒。注意,醒来并不一定马上得到执行的机会,而是放在可运行池里,让JVM去调度到运行态。在运行的程序也可以通过yield方法让本线程放到可运行池里,因此不要依赖这个方法,这个方法可能并没什么用。只作为一个参考手段。为了等待该线程执行结束,可以使用jion方法。
死亡态:死亡后不能复生。
接下来我来实现一个共享变量的控制实例:
创建一个我的对象,它有成员变量money,用两个线程去执行它,给一个消费金额不断的去消费,一直消费到0。
主线程中的测试:
public static void main(String args[]) throws InterruptedException { MyObject myObject = new MyObject(10); //定义两个线程来共享这个myObject Thread t1 = new Thread(myObject,"Thread-----A"); Thread t2 = new Thread(myObject,"Thread-----B"); t1.start(); t2.start(); //这里要用join方法,否则主线程在t1,t2执行的过程中可能并行执行,然后返回最后剩下的money,我想要显示的最终的结果,因此使用join方法是使t1,t2结束。 t1.join(); t2.join(); System.out.println("============主线程休眠1秒"); try { Thread.sleep(1000); Thread.yield();//将主线程放到线程池,这里不起作用。t1,t2已经死亡 } catch(Exception e) { e.printStackTrace(); } //判断最后的共享变量money的值 System.out.println("myObject当中Money最终为:"+myObject.money); }
接下来我们来共享变量的对象,如果没用控制方法同步
class MyObject implements Runnable{ //可以对成员变量加锁// volatile int money = 100; int money = 10000; //消费金额,用构造函数去初始化 private int consume; //如果这里不加synchronized方法去控制 @Override public void run() { // TODO Auto-generated method stub int i = 0; while(money > 0) { System.out.println(Thread.currentThread().getName()+"执行操作"+ (i+1) +"次"); money = getSumMoney(); System.out.println("money:"+money); i ++; } } private int getSumMoney() { return this.money - consume; } //构造方法,消费 MyObject(int consume) { this.consume = consume; } public int getMoney() { return money; }}
运行结果:
//省略前面......Thread-----A执行操作810次money:100Thread-----A执行操作811次money:90Thread-----A执行操作812次money:80Thread-----A执行操作813次money:70Thread-----A执行操作814次money:60Thread-----A执行操作815次money:50Thread-----A执行操作816次money:40Thread-----A执行操作817次money:30Thread-----A执行操作818次money:20Thread-----A执行操作819次money:10Thread-----A执行操作820次money:0Thread-----B执行操作181次money:-10============主线程休眠1秒myObject当中Money最终为:-10
最终为-10,因为最后结果出现了问题。
我们加上访问修饰符synchronized
运行结果:
//....//..//.Thread-----A执行操作994次money:60Thread-----A执行操作995次money:50Thread-----A执行操作996次money:40Thread-----A执行操作997次money:30Thread-----A执行操作998次money:20Thread-----A执行操作999次money:10Thread-----A执行操作1000次money:0============主线程休眠1秒myObject当中Money最终为:0
结果算是没问题了,但是这里为什么只有A方法得到了执行呢?我再来分析代码,发现是线程A占用了对象的锁一直没释放,让线程B没有机会执行。为了达到两个线程都能够执行的目的,再加上wait方法放弃锁。代码如下:
public synchronized void run() { // TODO Auto-generated method stub int i = 0; while(money > 0) { System.out.println(Thread.currentThread().getName()+"执行操作"+ (i+1) +"次"); money = getSumMoney(); System.out.println("money:"+money); try { System.out.println(Thread.currentThread().getName() + "本线程放弃锁"); wait(50); } catch(Exception e) { e.printStackTrace(); } i ++; } }
运行结果:
//..........Thread-----A本线程放弃锁Thread-----B执行操作496次money:90Thread-----B本线程放弃锁Thread-----A执行操作496次money:80Thread-----A本线程放弃锁Thread-----B执行操作497次money:70Thread-----B本线程放弃锁Thread-----A执行操作497次money:60Thread-----A本线程放弃锁Thread-----B执行操作498次money:50Thread-----B本线程放弃锁Thread-----A执行操作498次money:40Thread-----A本线程放弃锁Thread-----B执行操作499次money:30Thread-----B本线程放弃锁Thread-----A执行操作499次money:20Thread-----A本线程放弃锁Thread-----B执行操作500次money:10Thread-----B本线程放弃锁Thread-----A执行操作500次money:0Thread-----A本线程放弃锁============主线程休眠1秒myObject当中Money最终为:0
很好,问题得到了解决,交替执行并保证了数据的正确性。
- java多线程的共享变量访问控制实例
- Java多线程共享变量控制
- Java多线程共享变量控制
- Java多线程共享变量控制
- java 多线程访问共享变量不安全因素分析
- Java 多线程 变量共享
- java多线程共享变量
- 多线程共享实例变量例子
- java多线程范围内的共享变量
- 多线程的共享变量
- Java多线程-变量共享分析
- 多线程间变量的共享
- java多线程之共享变量的可见性、原子性
- 多线程 : 多线程共享局部变量的方法
- Java中方法和成员变量的访问控制
- java什么时候需要多线程 共享 变量
- Java: 简单模拟多线程访问同样变量导致的问题
- java多线程(对象和变量的并发访问)
- android开发第二弹--WebView总结
- 转 java Tomcat数据库连接池
- 一直以来对于返回jsp页面的认识错误
- PAT 1096. Consecutive Factors (20)
- WebService学习笔记(四)Map等非JavaBean类型传输
- java多线程的共享变量访问控制实例
- 一知半解之 shiro session 处方式
- 8.Android String相关类性能测试
- 每天工作4小时的程序员
- Linux-CentOS 配置国内YUM源
- 传播知识,分享快乐--我的相关资源下载(不定期更新)
- Android实现多个TextView同时显示跑马灯效果
- 【排序】希尔排序法
- 【Android】关于pix,dip,dip,sp等相关概念