java实现简单的销售统计,多线程中的大局信息统计的一种简单实现方式(java实现)...

多线程中的全局信息统计的一种简单实现方式(java实现)

如果你学过操作系统,我想你肯定对原子操作不会陌生,著名的哲学家就餐问题大家估计也不会陌生。如果现在有一个多线程的程序,有一个公共的访问变量,那么想正确的控制这个公共变量的值,每个学过计算机的人的处理方式肯定是使用一些互斥量,或者锁机制,或者信号量的方法保证对公共变量的访问时原子的。

当然自己实现这些操作也是不难的,但是现在java提供了一种更加简单搞笑的实现方式。

java.util.concurrent.atomic

类 AtomicLong

java.lang.Object

105701182.gifjava.lang.Number

105701182.gifjava.util.concurrent.atomic.AtomicLong

这个类AtomicLong是一个原子类,程序中对这种高变量的操作都是原子操作。

可以用原子方式更新的long值。有关原子变量属性的描述,请参阅java.util.concurrent.atomic包规范。AtomicLong可用在应用程序中(如以原子方式增加的序列号),并且不能用于替换Long。但是,此类确实扩展了Number,允许那些处理基于数字类的工具和实用工具进行统一访问。有关这个类的一个比较详细的介绍,有一个网址提供了下面的介绍。http://blog.csdn.net/jationxiaozi/article/details/6322151

下面我将介绍一个应用场景,可以很好地使用原子类AtomicLong来实现在多线程中正确无误的进行信息统计。

假设有一个应用,有多个线程,他们的工作是一致的,例如他们都是在生成产品,他们都能看见一个全局的变量count,这个变量时用来统计到现在为止所有的人一共生成了多少产品,显然为了能够保证准确性,我们必须保证所有的线程在更新count的时候其它线程不去访问count,而AtomicLong类型的变量正好符合这个要求。现在我们的主管人员会定期的去访问这个变量统计一下从开始工作到现在为止工厂的生成产品的平均速度。

为了满足如下的要求我写了一个简单的多线程中的全局信息统计的一种简单实现方式。

WorkThread,生产者的实现方式如下,

package com.jack.qiu.thread;

import java.util.concurrent.atomic.AtomicLong;

public class WorkThread extends Thread{

/**

* 将AtomicLong设定为静态的相当于公共变量

*/

public static AtomicLong count = new AtomicLong(0);

public static long timeBegin = System.currentTimeMillis();

//private String name;

//private int x;

//private Lock lock;

public WorkThread(String name)

{

this.setName(name);

//this.x = x;

//this.lock = lock;

}

/**

* 模拟生产过程

*/

private void doSomeThing()

{

long millSec = (long) (Math.random()*1000);

try {

Thread.sleep(millSec);//模拟生产过程

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return;

}

public void run()

{

while(true)

{

//here

doSomeThing();

/**

* 原子操作

*/

count.addAndGet(1);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

下面的线程模拟主管人员的工作,他会每10秒就获取当前的生产总量,然后计算生产速度

package com.jack.qiu.thread;

public class Statics extends Thread{

/**

* 设定7个工作人员

*/

WorkThread[] threads = new WorkThread[7];

private static String div(long begin,long now,long count)

{

double gap = (now-begin)/1000.0;

return String.format("%1.2f",count/gap);

}

public void run()

{

//Lock lock = new ReentrantLock(false);

for(int i=0;i

{

String threadName = "thread"+i;

threads[i] = new WorkThread(threadName);

}

for(int i=0;i

{

threads[i].start();

}

try

{

while(true)

{

Thread.sleep(10000);

System.out.println("--------jack statics-------");

/**

* 管理者获取当前的生产总数,为了保证所有的操作都是原子的使用了如下的操作

*/

long ccount = WorkThread.count.addAndGet(0);

System.out.println("from begin to now we have finished "+ ccount+" items");

System.out.println("the rate is "+div(WorkThread.timeBegin,System.currentTimeMillis(),ccount)+" per second\n\n");

}

}catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return;

}

}最后面的启动模拟程序的main函数如下:

package com.jack.qiu.test;

import com.jack.qiu.thread.Statics;

public class Main {

public static void main(String[] argv)

{

Statics stat = new Statics();

stat.start();

try {

stat.join();

} catch (InterruptedException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

好了我们看到了整个程序非常的简单,我们再对count进行统计和计算的时候没有只是用了AtomicLong类别给我们提供的一个方法,就是如此的简单高效。相信大家也是很期待运行结果吧。

--------jack statics-------

from begin to now we have finished 50 items

the rate is 5.00  per second

--------jack statics-------

from begin to now we have finished 95 items

the rate is 4.74  per second

--------jack statics-------

from begin to now we have finished 144 items

the rate is 4.79  per second

1楼qiuzhijieluojianping昨天 21:54有些错别字,其他都还挺好的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java实现多线程有以下几种方式: 1. 继承Thread类:创建一个继承自Thread类的子类,并重写其run()方法来定义线程的执行逻辑。然后通过创建子类的实例并调用start()方法来启动线程。 ```java class MyThread extends Thread { public run() { // 线程的执行逻辑 } } // 创建线程实例并启动线程 MyThread thread = new MyThread(); thread.start(); ``` 2. 实现Runnable接口:创建一个实现了Runnable接口的类,并实现其run()方法来定义线程的执行逻辑。然后通过创建该类的实例,并将其作为参数传递给Thread类的构造方法来创建线程对象,最后调用线程对象的start()方法来启动线程。 ```java class MyRunnable implements Runnable { public void run() { // 线程的执行逻辑 } } // 创建线程实例并启动线程 MyRunnable runnable = new MyRunnable(); Thread thread = new Thread(runnable); thread.start(); ``` 3. 使用匿名内部类:可以直接使用匿名内部类来实现Runnable接口或继承Thread类,并重写其run()方法来定义线程的执行逻辑。然后通过创建匿名内部类的实例并调用start()方法来启动线程。 ```java // 使用匿名内部类实现Runnable接口 Runnable runnable = new Runnable() { public void run() { // 线程的执行逻辑 } }; // 创建线程实例并启动线程 Thread thread = new Thread(runnable); thread.start(); // 使用匿名内部类继承Thread类 Thread thread = new Thread() { public void run() { // 线程的执行逻辑 } }; // 启动线程 thread.start(); ``` 4. 使用线程池:通过使用Java提供的线程池来管理线程的创建和执行。使用Executor框架的ThreadPoolExecutor类来创建线程池,并submit()方法提交任务给线程池执行。 ```java ExecutorService executor = Executors.newFixedThreadPool(5); Runnable runnable = new Runnable() { public void run() { // 线程的执行逻辑 } }; // 提交任务给线程池执行 executor.submit(runnable); // 关闭线程池 executor.shutdown(); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值