Ответ 1
Вот простой пример:
ThreadTest.java
public class ThreadTest
{
public static void main(String [] args)
{
MyThread t1 = new MyThread(0, 3, 300);
MyThread t2 = new MyThread(1, 3, 300);
MyThread t3 = new MyThread(2, 3, 300);
t1.start();
t2.start();
t3.start();
}
}
MyThread.java
public class MyThread extends Thread
{
private int startIdx, nThreads, maxIdx;
public MyThread(int s, int n, int m)
{
this.startIdx = s;
this.nThreads = n;
this.maxIdx = m;
}
@Override
public void run()
{
for(int i = this.startIdx; i < this.maxIdx; i += this.nThreads)
{
System.out.println("[ID " + this.getId() + "] " + i);
}
}
}
И некоторый вывод:
[ID 9] 1
[ID 10] 2
[ID 8] 0
[ID 10] 5
[ID 9] 4
[ID 10] 8
[ID 8] 3
[ID 10] 11
[ID 10] 14
[ID 10] 17
[ID 10] 20
[ID 10] 23
Объяснение. Каждый объект MyThread
пытается напечатать числа от 0 до 300, но они отвечают только за определенные области этого диапазона. Я решил разбить его по индексам, причем каждый поток прыгал вперед по количеству потоков. Итак, t1
имеет индекс 0, 3, 6, 9 и т.д.
Теперь, без ввода-вывода, тривиальные вычисления, подобные этому, могут по-прежнему выглядеть так, как потоки выполняются последовательно, поэтому я просто показал первую часть вывода. На моем компьютере после этого выходной поток с идентификатором 10 заканчивается сразу, а затем 9, затем 8. Если вы положили ожидание или доходность, вы можете увидеть его лучше:
MyThread.java
System.out.println("[ID " + this.getId() + "] " + i);
Thread.yield();
И вывод:
[ID 8] 0
[ID 9] 1
[ID 10] 2
[ID 8] 3
[ID 9] 4
[ID 8] 6
[ID 10] 5
[ID 9] 7
Теперь вы можете увидеть выполнение каждого потока, отказаться от управления на ранней стадии и следующего выполнения.