简体   繁体   English

多线程之间的对象共享

[英]Object sharing between multiple threads

My question is : 我的问题是:
Let say I have 假设我有

class Person{
    String name;
    int age;
}

And 2 threads T1, T2. 和2个线程T1,T2。 T1 sets name of Person and T2 sets age of person. T1设置人员name ,T2设置人员age
Condition is if NAME exist then only set AGE else wait() . 条件是如果NAME存在,则仅设置AGE else wait()
Please assist how to solve this question using Java. 请协助如何使用Java解决此问题。

Thanks, 谢谢,
Rahul. 拉胡尔

You can use a Condition syncronize two threads. 您可以使用条件同步两个线程。

Add Condition and ReentrantLock in Person class 在Person类中添加ConditionReentrantLock

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 set the name and signal: 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 wait until name has been set: 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();
        }
    }
}

In main thread start NameThread and AgeThread with parameters: 在主线程中,使用参数启动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();
    }

}

You can achieve that with CompletableFuture . 您可以使用CompletableFuture来实现。 The code might not be the best with respect to performance but relatively short and simple to maintain: 就性能而言,该代码可能不是最佳的,但相对较短且易于维护:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM