Запуск программы в течение 60 минут, и каждый поток использует другой идентификатор

Как убедиться, что каждый поток использует другой уникальный идентификатор, и этот идентификатор должен находиться между startExistingRange и endExistingRange. Поскольку я беспокоюсь, потому что программа должна работать в течение 60 минут, а до 60 минут возможно, что все идентификаторы будут использованы, тогда что мне делать. Должен ли я сбросить переменные? Что может быть лучшей практикой?

Например: — Поток 1 будет использовать 25, Поток 2 будет использовать 45 и т. д. и т. д.

class ThreadTask implements Runnable {
    private int id;

    public ThreadTask(int id) {
        this.id = id;
    }

    public void run() {
        System.out.println("Thread " + id);
    }
}

public class TestPool {

    public static void main(String[] args) {
        int size = 10;
        int durationOfRun = 60;
        int startExistingRange = 1;
        int endExistingRange = 1000;

        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(size); 

        // queue some tasks
        long startTime = System.currentTimeMillis();
        long endTime = startTime + (durationOfRun*60*1000);

        // Running it for 60 minutes
        while(System.currentTimeMillis() <= endTime) {
/* I want each thread uses different unique ID between startExistingRange
 and endExistingRange */
            service.submit(new ThreadTask(What should I pass 
                 here so that each thread is using different ID));
        }

        // wait for termination        
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    }
}

Обновлено: -

public class TestingPool {

    public static void main(String[] args) throws InterruptedException {
        int size = 10;
        int durationOfRun = 1;
        IdPool idPool = new IdPool();   
        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(size); 

        // queue some tasks
        long startTime = System.currentTimeMillis();
        long endTime = startTime + (durationOfRun * 60 * 1000L);

        // Getting and releasing id in while loop
        while(System.currentTimeMillis() <= endTime) {
            Integer id = idPool.getId();
            service.submit(new ThreadTask(idPool, id));
            idPool.releaseId(id);
        }

        // wait for termination        
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    }

}

class IdPool {
    private final LinkedList<Integer> availableIds = new LinkedList<Integer>();

    public IdPool() {
        for (int i = 1; i <= 1000; i++) {
            availableIds.add(i);
        }
        Collections.shuffle(availableIds);
    }

    public synchronized Integer getId() {
        return availableIds.removeFirst();
    }

    public synchronized void releaseId(Integer id) {
        availableIds.add(id);
    }
}


class ThreadTask implements Runnable {
    private IdPool idPool;
    private int kk;

    public ThreadTask(IdPool idPool, int s) {
        this.idPool = idPool;
        this.kk = s;
    }

    public void run() {
        //Integer id = idPool.getId();
        System.out.println("Task " + kk);
        //idPool.releaseId(id);
    }
}

person AKIWEB    schedule 25.05.2012    source источник


Ответы (3)


Вместо того, чтобы передавать идентификатор вашей задаче во время создания, пусть ваша задача получит свой идентификатор из пула доступных идентификаторов. Поскольку у вас 10 потоков, вам нужно всего 10 идентификаторов. Каждая задача получает идентификатор из пула при запуске и передает его в пул по завершении. Конечно, пул должен быть потокобезопасным:

public class IdPool {
    private final LinkedList<Integer> availableIds = new LinkedList<Integer>();

    public IdPool() {
        for (int i = 1; i <= 1000; i++) {
            availableIds.add(i);
        }
    }

    public synchronized Integer getId() {
        return availabeIds.removeFirst();
    }

    public synchronized void releaseId(Integer id) {
        availableIds.add(id);
    }
}


class ThreadTask implements Runnable {
    private IdPool idPool;

    public ThreadTask(IdPool idPool) {
        this.idPool = idPool;
    }

    public void run() {
        Integer id = idPool.getId();
        System.out.println("Task " + id);
        idPool.releaseId(id);
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        int size = 10;
        int durationOfRun = 60;
        IdPool idPool = new IdPool();   
        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(size); 

        // queue some tasks
        long startTime = System.currentTimeMillis();
        long endTime = startTime + (durationOfRun * 60 * 1000L);

        // Running it for 60 minutes
        while(System.currentTimeMillis() <= endTime) {
            service.submit(new ThreadTask(idPool));
        }

        // wait for termination        
        service.shutdown();
        service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    }
}
person JB Nizet    schedule 25.05.2012
comment
Итак, вы говорите: если у меня 1000 идентификаторов, мне нужно 1000 потоков, чтобы каждый мог использовать один уникальный идентификатор в этом диапазоне? Невозможно, чтобы каждый поток мог использовать несколько уникальных идентификаторов между этим диапазоном? Можете ли вы привести один пример на основе моего кода? Это мне очень поможет. - person AKIWEB; 25.05.2012
comment
Это не то, что я говорю. Вы просили найти способ для каждой задачи среди 10 одновременных задач использовать разные идентификаторы от 1 до 1000. Я просто сказал, что, поскольку у вас есть только 10 одновременных задач, нет необходимости в более чем 10 идентификаторах. И каждая задача могла получить свой идентификатор из пула доступных идентификаторов. - person JB Nizet; 25.05.2012
comment
Но проблема в том, что мне нужно более 10 идентификаторов, а может быть и более 1000. - person AKIWEB; 25.05.2012
comment
Либо вы соглашаетесь на повторное использование идентификатора, либо нет. Если вы не принимаете повторное использование, вы не можете отправить более 1000 задач. Если вы принимаете повторное использование, то достаточно 10 идентификаторов. Но у вас может быть пул из 1000 идентификаторов, если вы хотите, и моя стратегия все еще может быть использована. Вам просто нужно получить идентификатор из начала списка и вернуть идентификатор в конец списка. - person JB Nizet; 25.05.2012
comment
Я думаю, нам нужно повторно использовать идентификатор. Я думаю, вы можете показать мне один пример, который будет делать то же самое, что вы только что сказали, на основе моего кода? - person AKIWEB; 25.05.2012
comment
Если вы не знаете, что вам нужно, то начните с размышлений об этом и примите решение. Я отредактирую свой ответ, но это довольно простые вещи, которые вы могли бы понять сами. - person JB Nizet; 25.05.2012
comment
Я отредактировал ваш код, добавив свои изменения, так что должно быть примерно так? - person AKIWEB; 26.05.2012
comment
Да. Я удалил ненужные переменные, исправил отступы и использовал правильную типизацию для вычисления миллисекунд. - person JB Nizet; 26.05.2012
comment
Спасибо. Значит, в этом случае продолжительностьOfRun должна быть int или long? Я думаю, это должно быть долго? - person AKIWEB; 26.05.2012
comment
У меня есть еще один вопрос JB, вместо того, чтобы получать идентификатор и выпускать идентификатор в методе запуска, если я делаю то же самое в цикле while, тогда это нормально или нет? Я обновил свой вопрос, опубликовав код, в котором я получаю идентификатор и выпускаю идентификатор в цикле while внутри java main. - person AKIWEB; 26.05.2012
comment
Конечно нет. Если вы отправляете 2000 задач в цикле, после 1000-й не будет доступного идентификатора. Этот метод работает, потому что в вашем пуле потоков меньше 1000 потоков, а это означает, что в пуле всегда будут доступные идентификаторы. - person JB Nizet; 26.05.2012
comment
Я не думаю, поэтому я понимаю, что вы только что сказали. Значит, то, что я сделал в цикле while, неверно. Он всегда должен быть в методе запуска? Можете ли вы объяснить немного больше. - person AKIWEB; 26.05.2012
comment
Нет, это неправильно. Вы отправляете миллионы и миллионы задач в свой пул потоков. Столько, сколько можно создать за 60 минут. И для каждой задачи вы получаете идентификатор из пула, который имеет только 1000 доступных идентификаторов. На 1001-й задаче пул выдаст исключение NoSuchElementException, потому что список будет пуст. - person JB Nizet; 26.05.2012
comment
Я запустил тот же код, поместив их в цикл while, он не выдает никаких таких исключений. Я запустил его на одну минуту, и у меня не было таких исключений, просто он использует идентификатор, а после 1000 он снова использует идентификатор. - person AKIWEB; 26.05.2012
comment
Виноват. Освобождая идентификатор сразу после отправки задачи, вместо того, чтобы освобождать его после завершения задачи, вы просто отправляете миллионы задач с идентификаторами от 1 до 1000 и снова начиная с 1 и т. д. Но это не мешает нескольким одновременные задачи имеют одинаковый идентификатор. Например, если первая задача очень длинная, а остальные 999 очень короткие, 1001-я будет выполняться с идентификатором 1, а первая (также с идентификатором 1) будет выполняться до сих пор. - person JB Nizet; 26.05.2012

Вы можете отслеживать, какие идентификаторы уже используются в наборе (и еще один для неиспользуемых для удобства).

Затем вы можете запустить идентификаторы от 1 до 1000. Когда они закончатся, вы ищете значения, доступные в неиспользуемом наборе.

Каждый раз, когда вы запускаете поток, вы перемещаете этот идентификатор из неиспользуемого набора в используемый, каждый раз, когда поток завершается, вы делаете обратное.

Невозможно исчерпать идентификаторы, так как у вас одновременно работает не более 10 потоков.

person Attila    schedule 25.05.2012
comment
Итак, вы говорите: если у меня 1000 идентификаторов, мне нужно 1000 потоков, чтобы каждый мог использовать один уникальный идентификатор в этом диапазоне? Невозможно, чтобы каждый поток мог использовать несколько уникальных идентификаторов между этим диапазоном? Можете ли вы привести мне один пример, основанный на моем коде? - person AKIWEB; 25.05.2012
comment
Вам не нужно 1000 потоков, просто подождите, пока один из них не завершится, когда у вас закончатся потоки, и запустите его снова с новым идентификатором. - person Attila; 25.05.2012
comment
Можете ли вы показать мне один пример? Это мне очень поможет. А также в этом пуле должен быть потокобезопасный, верно? Единственное беспокойство, которое у меня есть, так как я работаю в течение 60 минут, так что за эти минуты вполне возможно, что все идентификаторы были использованы, верно? - person AKIWEB; 25.05.2012

Рассматривали ли вы возможность использования Thread.getID ().

Возвращает идентификатор этого потока. Идентификатор потока — это положительное длинное число, сгенерированное при создании этого потока. Идентификатор потока уникален и остается неизменным в течение всего времени его существования. Когда поток завершается, этот идентификатор потока может использоваться повторно.

Обратите внимание на мой акцент.

Затем вы можете добавить 100 000 * the number of seconds you have been running или что-то в этом роде.

Добавлено — по многочисленным просьбам:

public void run() {
  Thread me = Thread.currentThread();
  // Name me from my ID.
  me.setName("X-" + me.getId());
  ...
person OldCurmudgeon    schedule 25.05.2012
comment
Я не знаю о Thread.getID(). Можете ли вы показать мне один пример? - person AKIWEB; 25.05.2012