[英]Object sharing between multiple threads
我的問題是:
假設我有
class Person{
String name;
int age;
}
和2個線程T1,T2。 T1設置人員name
,T2設置人員age
。
條件是如果NAME存在,則僅設置AGE else wait()
。
請協助如何使用Java解決此問題。
謝謝,
拉胡爾
您可以使用條件同步兩個線程。
在Person類中添加Condition
和ReentrantLock
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class Person {
private ReentrantLock lock;
private Condition nameCondition;
private String name;
private Integer age;
public Person() {
this.lock = new ReentrantLock();
this.nameCondition = lock.newCondition();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Condition getNameCondition() {
return nameCondition;
}
public ReentrantLock getLock() {
return lock;
}
}
NameThread設置名稱和信號:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class NameRunnable implements Runnable{
private Person person;
private String name;
public NameRunnable(Person person, String name) {
this.person = person;
this.name = name;
}
@Override
public void run() {
ReentrantLock lock = person.getLock();
Condition condition = person.getNameCondition();
lock.lock();
try {
person.setName(name);
condition.signal();
} finally {
lock.unlock();
}
}
}
AgeThread等待設置名稱:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class AgeRunnable implements Runnable{
private Person person;
private Integer age;
public AgeRunnable(Person person, Integer age) {
this.person = person;
this.age = age;
}
@Override
public void run() {
ReentrantLock lock = person.getLock();
Condition condition = person.getNameCondition();
lock.lock();
try {
while (person.getName() == null) {
condition.await();
}
person.setAge(age);
} catch (InterruptedException e) {
// TODO
} finally {
lock.unlock();
}
}
}
在主線程中,使用參數啟動NameThread和AgeThread:
public class Main {
public static void main(String[] args) throws InterruptedException {
Person person = new Person();
NameRunnable nameRunnable = new NameRunnable(person, "Test");
AgeRunnable ageRunnable = new AgeRunnable(person, 10);
new Thread(nameRunnable).start();
new Thread(ageRunnable).start();
}
}
您可以使用CompletableFuture
來實現。 就性能而言,該代碼可能不是最佳的,但相對較短且易於維護:
public class Person {
final CompletableFuture<String> name = new CompletableFuture<>();
final CompletableFuture<Integer> age = new CompletableFuture<>();
public void setName(String value) {
System.out.println("Setting name to " + value);
name.complete(value);
System.out.println("Set name to " + value);
}
public void setAge(int value) {
System.out.println("Setting age to " + value);
// only set age when name is set, otherwise wait indefinitely
name.thenRun(() -> {
age.complete(value);
}).join();
System.out.println("Set age to " + value);
}
public String getName() {
return name.join();
}
public Integer getAge() {
return age.join();
}
private static void sleep(TimeUnit unit, int value) {
try {
Thread.sleep(unit.toMillis(value));
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new IllegalStateException("interrupted");
}
}
static final ExecutorService executor = Executors.newFixedThreadPool(10);
public static void main(String[] args) throws InterruptedException {
test("Thomas Edison", 1, 171, 2);
test("Elvis Presley", 2, 83, 1);
executor.shutdown();
}
static void test(final String name, final int secondsBeforeNameSet,
final int age, final int secondsBeforeAgeSet) throws InterruptedException {
final Person p = new Person();
executor.invokeAll(Arrays.asList(
Executors.callable(() -> {
sleep(TimeUnit.SECONDS, secondsBeforeAgeSet);
p.setAge(age);
}),
Executors.callable(() -> {
sleep(TimeUnit.SECONDS, secondsBeforeNameSet);
p.setName(name);
})
));
System.out.println("Person{ name:" + p.getName() + ", age:" + p.getAge() + "}");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.