Инициализация двух потоков одним и тем же экземпляром исполняемого файла - программирование
Подтвердить что ты не робот

Инициализация двух потоков одним и тем же экземпляром исполняемого файла

Неужели это плохое программирование для инициализации двух потоков одним и тем же экземпляром runnable? Какая разница при инициализации с отдельными экземплярами runnable и вообще ли разделение памяти на одном экземпляре runnable имеет какое-либо отношение к производительности?

public static void main(String[] args)throws Exception {
   H h = new H();
   H h2 = new H();
   Thread j = new Thread(h);
   j.setName("11");

   Thread jj = new Thread(h);//instead of new H()
   jj.setName("22");
   j.start();
   jj.start();
}

class H implements Runnable {
    public void run() {
        while(true) {
           System.out.println(Thread.currentThread().getName());
        }
    }
}
4b9b3361

Ответ 1

Это абсолютно нормально, если вы выполняете этот код, чтобы поддерживать это. Мало того, что он сохранит некоторую память, имея один экземпляр вместо нескольких экземпляров, но если эти потоки пытаются обмениваться данными через общие данные, тогда это может быть абсолютно необходимо!

По общему мнению, передача через разделяемое состояние - это то, что потоковая передача часто становится сложной, поэтому это нужно делать осторожно, но с точки зрения самой системы потоковой передачи абсолютно нет проблем, когда два потока вызывают метод run один экземпляр Runnable.

Ответ 2

Поскольку H не имеет какого-либо состояния экземпляра, использование нескольких экземпляров не имеет значения. Вам нужно позаботиться о том, чтобы экземпляры Runnable начали сохранять состояние.

public class Main implements Runnable {
    volatile int i;
        public void run() {
        for (i = 0; i < 100; i++) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        Main a = new Main();
        Thread t1 = new Thread(a);
        Thread t2 = new Thread(a);
        t1.start();
        t2.start();
    }        
}

Что печатается? Когда вам нужно разделить состояние между потоками, полезно использовать классы в java.util.concurrent. Они были написаны в основном экспертом по многопоточности (Дуг Ли, автор Concurrent Programming in Java) и проверены многими людьми. Спасите себя от сильной боли. :)

Ответ 3

Неужели это плохое программирование для инициализации двух потоков одним и тем же экземпляром runnable?

Не определенно. Однако если экземпляр Runnable имеет поля экземпляра, то вам нужно убедиться, что все доступ к полям по потоку правильно синхронизирован, и это сделает код более сложным.

Какая разница в инициализации с отдельными экземплярами runnable и вообще ли разделение мест памяти на один и тот же экземпляр runnable имеет какое-либо отношение к производительности?

Память, сохраненная при совместном использовании экземпляра Runnable между несколькими потоками, незначителен... если только Runnable не содержит значительного количества данных экземпляра. (И если это так, есть вероятность, что это сделает экземпляр несовместимым.)


Ваш класс H является примером, где совместное использование экземпляров безопасно, но бессмысленно, поскольку сохранение памяти незначительно. (A Runnable объект без полей экземпляра занимает примерно 8-16 байт, в зависимости от платформы.)

Ответ 4

Чтобы легко понять (на основе комментария Стивена), добавленный ниже программный блок о влиянии доступа к переменной экземпляра из несинхронизированного блока с тем же экземпляром Runnable отображает неожиданные результаты.

public class SynchronizedInstanceMethod implements Runnable{

private int counter;

public SynchronizedInstanceMethod(int counterValue){
    this.counter = counterValue;
}

private synchronized void displayMessage(){
    System.out.println(" Display Message ");
}

private void modifyCounter(){
    this.counter++;
    System.out.println("Value -- "+ this.counter);
}

@Override
public void run() {
    this.displayMessage();
    this.modifyCounter();
}

public static void main(String[] args) {
    SynchronizedInstanceMethod instance = new SynchronizedInstanceMethod(5);
    new Thread(instance).start();
    new Thread(instance).start();
}
}