「多线程计数器java」多线程计数器

博主:adminadmin 2023-01-01 02:33:06 1211

今天给各位分享多线程计数器java的知识,其中也会对多线程计数器进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

本文目录一览:

java在多线程环境下,为什么要为每个线程维护一个独立的程序计数器

程序计数器指向下一条指令(存储下一条CPU指令的地址),线程是CPU的执行和调度单元,不同的线程的执行路径(执行的指令)、和执行时序不一样,所以每个线程有自己私有的程序计数器和堆栈。

Java多线程的优先级

优先级线程的优先级(Priority)告诉调试程序该线程的重要程度有多大 如果有大量线程都被堵塞 都在等候运行 调试程序会首先运行具有最高优先级的那个线程 然而 这并不表示优先级较低的线程不会运行(换言之 不会因为存在优先级而导致死锁) 若线程的优先级较低 只不过表示它被准许运行的机会小一些而已 可用getPriority()方法读取一个线程的优先级 并用setPriority()改变它 在下面这个程序片中 大家会发现计数器的计数速度慢了下来 因为它们关联的线程分配了较低的优先级 //: Counter java// Adjusting the priorities of threadsimport java awt *;import java awt event *;import java applet *;class Ticker extends Thread { private Button b = new Button( Toggle ) incPriority = new Button( up ) decPriority = new Button( down ); private TextField t = new TextField( ) pr = new TextField( ); // Display priority private int count = ; private boolean runFlag = true; public Ticker (Container c) { b addActionListener(new ToggleL()); incPriority addActionListener(new UpL()); decPriority addActionListener(new DownL()); Panel p = new Panel(); p add(t); p add(pr); p add(b); p add(incPriority); p add(decPriority); c add(p); } class ToggleL implements ActionListener { public void actionPerformed(ActionEvent e) { runFlag = !runFlag; } } class UpL implements ActionListener { public void actionPerformed(ActionEvent e) { int newPriority = getPriority() + ; if(newPriority Thread MAX_PRIORITY) newPriority = Thread MAX_PRIORITY; setPriority(newPriority); } } class DownL implements ActionListener { public void actionPerformed(ActionEvent e) { int newPriority = getPriority() ; if(newPriority Thread MIN_PRIORITY) newPriority = Thread MIN_PRIORITY; setPriority(newPriority); } } public void run() { while (true) { if(runFlag) { t setText(Integer toString(count++)); pr setText( Integer toString(getPriority())); } yield(); } }}public class Counter extends Applet { private Button start = new Button( Start ) upMax = new Button( Inc Max Priority ) downMax = new Button( Dec Max Priority ); private boolean started = false; private static final int SIZE = ; private Ticker [] s = new Ticker [SIZE]; private TextField mp = new TextField( ); public void init() { for(int i = ; i s.length; i++) s[i] = new Ticker2(this); add(new Label("MAX_PRIORITY = " + Thread.MAX_PRIORITY)); add(new Label("MIN_PRIORITY = " + Thread.MIN_PRIORITY)); add(new Label("Group Max Priority = ")); add(mp); add(start); add(upMax); add(downMax); start.addActionListener(new StartL()); upMax.addActionListener(new UpMaxL()); downMax.addActionListener(new DownMaxL()); showMaxPriority(); // Recursively display parent thread groups: ThreadGroup parent = s[0].getThreadGroup().getParent(); while(parent != null) { add(new Label( "Parent threadgroup max priority = " + parent.getMaxPriority())); parent = parent.getParent(); } } public void showMaxPriority() { mp.setText(Integer.toString( s[0].getThreadGroup().getMaxPriority())); } class StartL implements ActionListener { public void actionPerformed(ActionEvent e) { if(!started) { started = true; for(int i = 0; i s.length; i++) s[i].start(); } } } class UpMaxL implements ActionListener { public void actionPerformed(ActionEvent e) { int maxp = s[0].getThreadGroup().getMaxPriority(); if(++maxp Thread.MAX_PRIORITY) maxp = Thread.MAX_PRIORITY; s[0].getThreadGroup().setMaxPriority(maxp); showMaxPriority(); } } class DownMaxL implements ActionListener { public void actionPerformed(ActionEvent e) { int maxp = s[0].getThreadGroup().getMaxPriority(); if(--maxp Thread.MIN_PRIORITY) maxp = Thread.MIN_PRIORITY; s[0].getThreadGroup().setMaxPriority(maxp); showMaxPriority(); } } public static void main(String[] args) { Counter5 applet = new Counter5(); Frame aFrame = new Frame("Counter5"); aFrame.addWindowListener( new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); aFrame.add(applet, BorderLayout.CENTER); aFrame.setSize(300, 600); applet.init(); applet.start(); aFrame.setVisible(true); }} ///:~Ticker采用本章前面构造好的形式,但有一个额外的TextField(文本字段),用于显示线程的优先级;以及两个额外的按钮,用于人为提高及降低优先级。WInGWit.也要注意yield()的用法,它将控制权自动返回给调试程序(机制)。若不进行这样的处理,多线程机制仍会工作,但我们会发现它的运行速度慢了下来(试试删去对yield()的调用)。亦可调用sleep(),但假若那样做,计数频率就会改由sleep()的持续时间控制,而不是优先级。Counter5中的init()创建了由10个Ticker2构成的一个数组;它们的按钮以及输入字段(文本字段)由Ticker2构建器置入窗体。Counter5增加了新的按钮,用于启动一切,以及用于提高和降低线程组的最大优先级。除此以外,还有一些标签用于显示一个线程可以采用的最大及最小优先级;以及一个特殊的文本字段,用于显示线程组的最大优先级(在下一节里,我们将全面讨论线程组的问题)。最后,父线程组的优先级也作为标签显示出来。按下“up”(上)或“down”(下)按钮的时候,会先取得Ticker2当前的优先级,然后相应地提高或者降低。运行该程序时,我们可注意到几件事情。首先,线程组的默认优先级是5。即使在启动线程之前(或者在创建线程之前,这要求对代码进行适当的修改)将最大优先级降到5以下,每个线程都会有一个5的默认优先级。最简单的测试是获取一个计数器,将它的优先级降低至1,此时应观察到它的计数频率显著放慢。现在试着再次提高优先级,可以升高回线程组的优先级,但不能再高了。现在将线程组的优先级降低两次。线程的优先级不会改变,但假若试图提高或者降低它,就会发现这个优先级自动变成线程组的优先级。此外,新线程仍然具有一个默认优先级,即使它比组的优先级还要高(换句话说,不要指望利用组优先级来防止新线程拥有比现有的更高的优先级)。最后,试着提高组的最大优先级。可以发现,这样做是没有效果的。我们只能减少线程组的最大优先级,而不能增大它。 lishixinzhi/Article/program/Java/gj/201311/27587

Java多线程之Atomic:原子变量与原子类

一 何谓Atomic?

Atomic一词跟原子有点关系 后者曾被人认为是最小物质的单位 计算机中的Atomic是指不能分割成若干部分的意思 如果一段代码被认为是Atomic 则表示这段代码在执行过程中 是不能被中断的 通常来说 原子指令由硬件提供 供软件来实现原子方法(某个线程进入该方法后 就不会被中断 直到其执行完成)

在x 平台上 CPU提供了在指令执行期间对总线加锁的手段 CPU芯片上有一条引线#HLOCK pin 如果汇编语言的程序中在一条指令前面加上前缀 LOCK 经过汇编以后的机器代码就使CPU在执行这条指令的时候把#HLOCK pin的电位拉低 持续到这条指令结束时放开 从而把总线锁住 这样同一总线上别的CPU就暂时不能通过总线访问内存了 保证了这条指令在多处理器环境中的原子性

二 ncurrent中的原子变量

无论是直接的还是间接的 几乎 ncurrent 包中的所有类都使用原子变量 而不使用同步 类似 ConcurrentLinkedQueue 的类也使用原子变量直接实现无等待算法 而类似 ConcurrentHashMap 的类使用 ReentrantLock 在需要时进行锁定 然后 ReentrantLock 使用原子变量来维护等待锁定的线程队列

如果没有 JDK 中的 JVM 改进 将无法构造这些类 这些改进暴露了(向类库 而不是用户类)接口来访问硬件级的同步原语 然后 ncurrent 中的原子变量类和其他类向用户类公开这些功能

ncurrent atomic的原子类

这个包里面提供了一组原子类 其基本的特性就是在多线程环境下 当有多个线程同时执行这些类的实例包含的方法时 具有排他性 即当某个线程进入方法 执行其中的指令时 不会被其他线程打断 而别的线程就像自旋锁一样 一直等到该方法执行完成 才由JVM从等待队列中选择一个另一个线程进入 这只是一种逻辑上的理解 实际上是借助硬件的相关指令来实现的 不会阻塞线程(或者说只是在硬件级别上阻塞了) 其中的类可以分成 组

AtomicBoolean AtomicInteger AtomicLong AtomicReference

AtomicIntegerArray AtomicLongArray

AtomicLongFieldUpdater AtomicIntegerFieldUpdater AtomicReferenceFieldUpdater

AtomicMarkableReference AtomicStampedReference AtomicReferenceArray

其中AtomicBoolean AtomicInteger AtomicLong AtomicReference是类似的

首先AtomicBoolean AtomicInteger AtomicLong AtomicReference内部api是类似的 举个AtomicReference的例子

使用AtomicReference创建线程安全的堆栈

Java代码

public class LinkedStackT {

private AtomicReferenceNodeT》 stacks = new AtomicReferenceNodeT》()

public T push(T e) {

NodeT oldNode newNode;

while (true) { //这里的处理非常的特别 也是必须如此的

oldNode = stacks get()

newNode = new NodeT(e oldNode)

if (pareAndSet(oldNode newNode)) {

return e;

}

}

}

public T pop() {

NodeT oldNode newNode;

while (true) {

oldNode = stacks get()

newNode = oldNode next;

if (pareAndSet(oldNode newNode)) {

return oldNode object;

}

}

}

private static final class NodeT {

private T object;

private NodeT next;

private Node(T object NodeT next) {

this object = object;

this next = next;

}

}

}

然后关注字段的原子更新

AtomicIntegerFieldUpdaterT/AtomicLongFieldUpdaterT/AtomicReferenceFieldUpdaterT V是基于反射的原子更新字段的值

相应的API也是非常简

单的 但是也是有一些约束的

( )字段必须是volatile类型的!volatile到底是个什么东西 请查看

( )字段的描述类型(修饰符public/protected/default/private)是与调用者与操作对象字段的关系一致 也就是说调用者能够直接操作对象字段 那么就可以反射进行原子操作 但是对于父类的字段 子类是不能直接操作的 尽管子类可以访问父类的字段

( )只能是实例变量 不能是类变量 也就是说不能加static关键字

( )只能是可修改变量 不能使final变量 因为final的语义就是不可修改 实际上final的语义和volatile是有冲突的 这两个关键字不能同时存在

( )对于AtomicIntegerFieldUpdater和AtomicLongFieldUpdater只能修改int/long类型的字段 不能修改其包装类型(Integer/Long) 如果要修改包装类型就需要使用AtomicReferenceFieldUpdater

在下面的例子中描述了操作的方法

[java]

import ncurrent atomic AtomicIntegerFieldUpdater;

public class AtomicIntegerFieldUpdaterDemo {

class DemoData{

public volatile int value = ;

volatile int value = ;

protected volatile int value = ;

private volatile int value = ;

}

AtomicIntegerFieldUpdaterDemoData getUpdater(String fieldName) {

return AtomicIntegerFieldUpdater newUpdater(DemoData class fieldName)

}

void doit() {

DemoData data = new DemoData()

System out println( == +getUpdater( value ) getAndSet(data ))

System out println( == +getUpdater( value ) incrementAndGet(data))

System out println( == +getUpdater( value ) decrementAndGet(data))

System out println( true == +getUpdater( value ) pareAndSet(data ))

}

public static void main(String[] args) {

AtomicIntegerFieldUpdaterDemo demo = new AtomicIntegerFieldUpdaterDemo()

demo doit()

}

}

在上面的例子中DemoData的字段value /value 对于AtomicIntegerFieldUpdaterDemo类是不可见的 因此通过反射是不能直接修改其值的

AtomicMarkableReference类描述的一个Object Boolean的对 可以原子的修改Object或者Boolean的值 这种数据结构在一些缓存或者状态描述中比较有用 这种结构在单个或者同时修改Object/Boolean的时候能够有效的提高吞吐量

AtomicStampedReference类维护带有整数 标志 的对象引用 可以用原子方式对其进行更新 对比AtomicMarkableReference类的Object Boolean AtomicStampedReference维护的是一种类似Object int的数据结构 其实就是对对象(引用)的一个并发计数 但是与AtomicInteger不同的是 此数据结构可以携带一个对象引用(Object) 并且能够对此对象和计数同时进行原子操作

在本文结尾会提到 ABA问题 而AtomicMarkableReference/AtomicStampedReference在解决 ABA问题 上很有用

三 Atomic类的作用

使得让对单一数据的操作 实现了原子化

使用Atomic类构建复杂的 无需阻塞的代码

访问对 个或 个以上的atomic变量(或者对单个atomic变量进行 次或 次以上的操作)通常认为是需要同步的 以达到让这些操作能被作为一个原子单元

无锁定且无等待算法

基于 CAS (pare and swap)的并发算法称为 无锁定算法 因为线程不必再等待锁定(有时称为互斥或关键部分 这取决于线程平台的术语) 无论 CAS 操作成功还是失败 在任何一种情况中 它都在可预知的时间内完成 如果 CAS 失败 调用者可以重试 CAS 操作或采取其他适合的操作

如果每个线程在其他线程任意延迟(或甚至失败)时都将持续进行操作 就可以说该算法是 无等待的 与此形成对比的是 无锁定算法要求仅 某个线程总是执行操作 (无等待的另一种定义是保证每个线程在其有限的步骤中正确计算自己的操作 而不管其他线程的操作 计时 交叉或速度 这一限制可以是系统中线程数的函数 例如 如果有 个线程 每个线程都执行一次CasCounter increment() 操作 最坏的情况下 每个线程将必须重试最多九次 才能完成增加 )

再过去的 年里 人们已经对无等待且无锁定算法(也称为 无阻塞算法)进行了大量研究 许多人通用数据结构已经发现了无阻塞算法 无阻塞算法被广泛用于操作系统和 JVM 级别 进行诸如线程和进程调度等任务 虽然它们的实现比较复杂 但相对于基于锁定的备选算法 它们有许多优点 可以避免优先级倒置和死锁等危险 竞争比较便宜 协调发生在更细的粒度级别 允许更高程度的并行机制等等

常见的

非阻塞的计数器Counter

非阻塞堆栈ConcurrentStack

lishixinzhi/Article/program/Java/gj/201311/27474

怎么知道java多线程都已经运行结束

一、使用java.util.concurrent.CountDownLatch

Java的util.concurrent包里面的CountDownLatch其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,同时只能有一个线程去操作这个计数器,也就是同时只能有一个线程去减这个计数器里面的值。

你可以向CountDownLatch对象设置一个初始的数字作为计数值,任何调用这个对象上的await()方法都会阻塞,直到这个计数器的计数值被其他的线程减为0为止。

CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这

个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个

CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个

CountDownLatch对象的计数值减到0为止。

举个例子,有三个工人在为老板干活,这个老板有一个习惯,就是当三个工人把一天的活都

干完了的时候,他就来检查所有工人所干的活。记住这个条件:三个工人先全部干完活,老板才检查。所以在这里用Java代码设计两个类,Worker代表工

人,Boss代表老板,具体的代码实现如下:

Worker类(单独的线程):

package cn.edu.bupt.thread.threadnotify;

import java.util.Random;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.TimeUnit;

public class Worker implements Runnable

{

private CountDownLatch downLatch;

private String name;

public Worker(CountDownLatch downLatch, String name)

{

this.downLatch = downLatch;

this.name = name;

}

@Override

public void run()

{

this.doWork();

try

{

TimeUnit.SECONDS.sleep(new Random().nextInt(10));

}

catch (InterruptedException ie)

{

}

System.out.println(this.name + "活干完了!");

this.downLatch.countDown();

}

private void doWork()

{

System.out.println(this.name + "正在干活...");

}

}

Boss类(单独的线程):

package cn.edu.bupt.thread.threadnotify;

import java.util.concurrent.CountDownLatch;

public class Boss implements Runnable

{

private CountDownLatch downLatch;

public Boss(CountDownLatch downLatch)

{

this.downLatch = downLatch;

}

@Override

public void run()

{

System.out.println("老板正在等所有的工人干完活......");

try

{

this.downLatch.await();

}

catch (InterruptedException e)

{

}

System.out.println("工人活都干完了,老板开始检查了!");

}

}

Main:

package cn.edu.bupt.thread.threadnotify;

import java.util.concurrent.CountDownLatch;

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

public class CountDownLatchDemo

{

public static void main(String[] args)

{

ExecutorService executor = Executors.newCachedThreadPool();

CountDownLatch latch = new CountDownLatch(3);

Worker w1 = new Worker(latch, "张三");

Worker w2 = new Worker(latch, "李四");

Worker w3 = new Worker(latch, "王二");

Boss boss = new Boss(latch);

executor.execute(boss);

executor.execute(w3);

executor.execute(w2);

executor.execute(w1);

executor.shutdown();

}

}

上例中的的ExecutorService接口和Executors类的作用类似于new Thread(Runnable r).start()的作用,就是启动一个新的线程。

Java 多线程中,我如何让开着的多线程执行完一批任务后 在继续执行另一批任务?

设置一个计数器,每个线程执行完后计数器加一然后查看计数器是否已满(任务都完成),没有的话就阻塞,是的话就唤醒其他所有线程,大家一起来执行下一次任务。要注意公用的计数器的线程安全!

多线程计数器java的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于多线程计数器、多线程计数器java的信息别忘了在本站进行查找喔。