Java 使用线程修改对象
我是新手。我想让两个线程将一个整数增加到某个值。因为int类型是不可变的,所以我切换到原子整数。我还尝试将int封装到类中,但也没有成功。我还尝试了静态/易失性int,但没有成功。我还尝试使用公平政策。主要问题是“counterObj”没有正确递增,即使它被注入到两个线程中,它仍然被设置为0 我预期的跑步行为:Java 使用线程修改对象,java,java-threads,Java,Java Threads,我是新手。我想让两个线程将一个整数增加到某个值。因为int类型是不可变的,所以我切换到原子整数。我还尝试将int封装到类中,但也没有成功。我还尝试了静态/易失性int,但没有成功。我还尝试使用公平政策。主要问题是“counterObj”没有正确递增,即使它被注入到两个线程中,它仍然被设置为0 我预期的跑步行为: thread value thread 0 0 thread 1 1 thread 0 2 ... 到目前为止我写的是: import java.u
thread value
thread 0 0
thread 1 1
thread 0 2
...
到目前为止我写的是:
import java.util.concurrent.atomic.AtomicInteger;
public class Application {
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void launch() throws InterruptedException {
int increments = 100;
AtomicInteger counterObj = new AtomicInteger(0);
CounterThread th1 = new CounterThread("1", counterObj, increments);
CounterThread th2 = new CounterThread("2", counterObj, increments);
th1.start();
th2.start();
System.out.println(counterObj.get());
}
}
及
导入java.util.concurrent.AtomicInteger;
公共类计数器线程实现可运行{
私有最终字符串threadID;
私有原子;
私有内边界;
公共计数器线程(字符串threadID,原子整数计数器,int-bound){
this.threadID=threadID;
this.counterObj=计数器;
this.bound=bound;
}
@凌驾
公共同步的无效运行(){
while(counterObj.get()
干杯 我认为您的程序在线程有机会做任何事情之前就已经退出了(可能是由于启动和连接的顺序。我会将您的线程启动逻辑移到main(或launch)方法中。如下所示
Thread thread1 = new Thread(new MyCounterRunnable("1", counterObj, increments));
Thread thread2 = new Thread(new MyCounterRunnable("2", counterObj, increments));
然后,在main中,您需要在启动线程后调用join…如下所示:
thread1.start(); // starts first thread.
thread2.start(); // starts second thread.
thread1.join(); // don't let main exit until thread 1 is done.
thread2.join(); // don't let main exit until thread 2 is done.
我认为你的程序在你的线程有机会做任何事情之前就已经退出了(可能是因为你的启动和连接的顺序。我会将你的线程启动逻辑移到你的main(或launch)方法中。如下所示
Thread thread1 = new Thread(new MyCounterRunnable("1", counterObj, increments));
Thread thread2 = new Thread(new MyCounterRunnable("2", counterObj, increments));
然后,在main中,您需要在启动线程后调用join…如下所示:
thread1.start(); // starts first thread.
thread2.start(); // starts second thread.
thread1.join(); // don't let main exit until thread 1 is done.
thread2.join(); // don't let main exit until thread 2 is done.
您真正想要的是一次只让一个线程增加一个int。 int变量是同步块中所需的资源,因此不同的线程可以一次递增一个。 这可以单独使用syncrhonize来完成。 免责声明:我没有运行代码,因此它可能会有一些打字错误或异常从应用程序类中删除
public class Application {
private int theVar = 0;
private int increments = 100;
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized addOne(){
this.theVar++;
}
private void launch() throws InterruptedException {
Runnable counter1 = new Counter(this, increments), counter2 = new Counter(this, increments);
Thread t1 = new Thread(counter1);
Thread t2 = new Thread(counter2);
t1.start();
t2.start();
}
}
柜台
public class Counter implements Runnable{
private Application app;
int rounds = -1;
public Counter(Application app, rounds){
this.app = app;
this.rounds = rounds;
}
public void run(){
while(int i=0; i<rounds; i++){
this.app.addOne();
}
}
}
公共类计数器实现可运行{
私人应用程序;
整数回合=-1;
公共柜台(应用程序、轮次){
this.app=app;
这个。轮数=轮数;
}
公开募捐{
而(inti=0;i您真正想要的是一次只让一个线程增加一个int。
int变量是同步块中所需的资源,因此不同的线程可以一次递增一个。
这可以单独使用syncrhonize来完成。
免责声明:我没有运行代码,因此它可能会有一些打字错误或异常从应用程序类中删除
public class Application {
private int theVar = 0;
private int increments = 100;
public static void main(String[] args) {
Application app = new Application();
try {
app.launch();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public synchronized addOne(){
this.theVar++;
}
private void launch() throws InterruptedException {
Runnable counter1 = new Counter(this, increments), counter2 = new Counter(this, increments);
Thread t1 = new Thread(counter1);
Thread t2 = new Thread(counter2);
t1.start();
t2.start();
}
}
柜台
public class Counter implements Runnable{
private Application app;
int rounds = -1;
public Counter(Application app, rounds){
this.app = app;
this.rounds = rounds;
}
public void run(){
while(int i=0; i<rounds; i++){
this.app.addOne();
}
}
}
公共类计数器实现可运行{
私人应用程序;
整数回合=-1;
公共柜台(应用程序、轮次){
this.app=app;
这个。轮数=轮数;
}
公开募捐{
虽然(inti=0;i我已经包含了对AtomicInteger的双重检查,但这似乎是您一直试图实现的
import java.util.concurrent.atomic.AtomicInteger;
public class DualCounters{
public static void main(String[] args) throws Exception{
AtomicInteger i = new AtomicInteger(0);
int bounds = 3;
Thread a = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("a last " + last);
});
Thread b = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("b last " + last);
});
a.start();
b.start();
a.join();
b.join();
System.out.println(i.get() + " afterwards");
}
}
我已经包含了对AtomicInteger的双重检查,这似乎是您一直试图实现的
import java.util.concurrent.atomic.AtomicInteger;
public class DualCounters{
public static void main(String[] args) throws Exception{
AtomicInteger i = new AtomicInteger(0);
int bounds = 3;
Thread a = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("a last " + last);
});
Thread b = new Thread(()->{
int last = 0;
while(i.get()<bounds){
synchronized(i){
if(i.get()<bounds){
last = i.getAndIncrement();
}
}
}
System.out.println("b last " + last);
});
a.start();
b.start();
a.join();
b.join();
System.out.println(i.get() + " afterwards");
}
}
AtomicInteger
负责原子性本身,因此您不需要使用synchronized
——但前提是您遵守规则,并在一次调用中执行原子操作
您没有做到这一点,因为您调用了counterObj.get()
,然后根据结果counterObj.incrementAndGet()
。您需要避免这种情况,因为您希望检查和更新是同一工作原子块的一部分
您可以通过以下方式接近:
while(counterObj.incrementAndGet() < bound) {} ;
while(counterObj.incrementAndGet()
但这将始终至少增加一次,这可能太多了
稍微涉及:
IntUnaryOperator incrementWithLimit = x ->
( x < bound ? x + 1 : x );
while(counterObj.updateAndGet(incrementWithLimit) < bound) {};
IntUnaryOperator incrementWithLimit=x->
(x
也就是说,我们已经创建了一个函数,它只在一个数小于界值时递增一个数,我们告诉AtomicInteger
应用这个函数。AtomicInteger
处理原子性本身,所以你不需要使用同步的
——但前提是你要遵守规则,并且在一个电话
您没有做到这一点,因为您调用了counterObj.get()
,然后根据结果counterObj.incrementAndGet()
。您需要避免这种情况,因为您希望检查和更新是同一工作原子块的一部分
您可以通过以下方式接近:
while(counterObj.incrementAndGet() < bound) {} ;
while(counterObj.incrementAndGet()
但这将始终至少增加一次,这可能太多了
稍微涉及:
IntUnaryOperator incrementWithLimit = x ->
( x < bound ? x + 1 : x );
while(counterObj.updateAndGet(incrementWithLimit) < bound) {};
IntUnaryOperator incrementWithLimit=x->
(x
也就是说,我们创建了一个函数,该函数仅在数值小于界限时递增数值,我们告诉AtomicInteger
应用该函数。您的代码有几个问题:
方法仅在线程已启动时有效,否则它将不起任何作用。因此,您必须对代码重新排序,但如果您只是将join方法移动到start之后,当通过调用CounterThread.start启动第一个线程时,主线程将等待启动的线程完成,并在中阻塞rong>Thread.join 方法,只有这样才能继续启动