簡體   English   中英

多線程之間的對象共享

[英]Object sharing between multiple threads

我的問題是:
假設我有

class Person{
    String name;
    int age;
}

和2個線程T1,T2。 T1設置人員name ,T2設置人員age
條件是如果NAME存在,則僅設置AGE else wait()
請協助如何使用Java解決此問題。

謝謝,
拉胡爾

您可以使用條件同步兩個線程。

在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設置名稱和信號:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM