Java同時/マルチスレッド
10446 ワード
Javaマルチスレッド
スレッドを実装する2つの方法:
a.Threadクラスを継承し、start()を起動します.
b.Runnableインタフェースを実現し、run方法を実現する.
1.基本スレッド
package com.sam.thread; public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; public SimpleThread() { super(""+++threadCount);//store the thread name start(); } public String toString() { return "#"+ getName() + ": "+ countDown; } public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new SimpleThread(); } } }
結果:
2.yield()は、譲歩して、他のスレッドにCPUを使用させ、結果をより均衡させることができます.
結果:
3.sleep、しばらく休眠してから実行する
結果:
4.優先度setPriority()
結果:優先度の高い先行実行
5.バックグラウンドスレッド(daemon)
バックグラウンド以外のすべてのスレッドが終了すると、スレッドは終了します.例えば、ある時点でスレッドがsleepになり、プログラムが終了します.
結果:
6.join()とinterrupt()
結果:
7.Runnableインタフェース
runnableインタフェース自体はスレッドの特性を持たず、実行するか、個別のThreadオブジェクトを作成します.
8.リソースへの不正アクセス
結果:
9.共有リソース競合の解決
共有リソースにアクセスする各メソッドにsynchronizedを追加する必要があります.そうしないと、追加しないメソッドはロックを無視します.
10. volatile
コンパイラの最適化は禁止され、スレッドはオブジェクトのプライベートコピーを保持できず、効率に影響します.
11.臨界領域
複数のスレッドアクセスメソッドの一部のコードを防止します.
12.スレッドの状態
新規(new)
準備完了(Runnable)
死亡(Dead)
ブロッキング(Blocked)
13. notify()
wait()のスレッドを起動します.
zz
スレッドを実装する2つの方法:
a.Threadクラスを継承し、start()を起動します.
b.Runnableインタフェースを実現し、run方法を実現する.
1.基本スレッド
package com.sam.thread; public class SimpleThread extends Thread { private int countDown = 5; private static int threadCount = 0; public SimpleThread() { super(""+++threadCount);//store the thread name start(); } public String toString() { return "#"+ getName() + ": "+ countDown; } public void run() { while (true) { System.out.println(this); if (--countDown == 0) return; } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new SimpleThread(); } } }
package com.sam.thread;
public class SimpleThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public SimpleThread() {
super(" " + ++threadCount); // store the thread name
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new SimpleThread();
}
}
}
結果:
# 1: 5
# 1: 4
# 1: 3
# 1: 2
# 1: 1
# 3: 5
# 3: 4
# 3: 3
# 3: 2
# 3: 1
# 2: 5
# 5: 5
# 5: 4
# 5: 3
# 5: 2
# 5: 1
# 2: 4
# 2: 3
# 2: 2
# 2: 1
# 4: 5
# 4: 4
# 4: 3
# 4: 2
# 4: 1
2.yield()は、譲歩して、他のスレッドにCPUを使用させ、結果をより均衡させることができます.
package com.sam.thread;
public class YieldThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public YieldThread() {
super(" " + ++threadCount); // store the thread name
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
yield();
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new YieldThread();
}
}
}
結果:
# 1: 5
# 2: 5
# 3: 5
# 1: 4
# 2: 4
# 5: 5
# 3: 4
# 1: 3
# 5: 4
# 3: 3
# 1: 2
# 5: 3
# 3: 2
# 1: 1
# 5: 2
# 4: 5
# 3: 1
# 5: 1
# 2: 3
# 4: 4
# 2: 2
# 2: 1
# 4: 3
# 4: 2
# 4: 1
3.sleep、しばらく休眠してから実行する
package com.sam.thread;
public class SleepThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public SleepThread() {
super(" " + ++threadCount); // store the thread name
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
try {
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new SleepThread();
}
}
}
結果:
# 1: 5
# 3: 5
# 2: 5
# 5: 5
# 4: 5
# 1: 4
# 2: 4
# 4: 4
# 3: 4
# 5: 4
# 1: 3
# 2: 3
# 3: 3
# 4: 3
# 5: 3
# 2: 2
# 4: 2
# 3: 2
# 1: 2
# 5: 2
# 1: 1
# 2: 1
# 4: 1
# 3: 1
# 5: 1
4.優先度setPriority()
package com.sam.thread;
public class PriorityThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public PriorityThread(int priority) {
super(" " + ++threadCount); // store the thread name
setPriority(priority);
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) {
new PriorityThread(Thread.MAX_PRIORITY);
for (int i = 0; i < 5; i++) {
new PriorityThread(Thread.MIN_PRIORITY);
}
}
}
結果:優先度の高い先行実行
# 1: 5
# 1: 4
# 1: 3
# 1: 2
# 1: 1
# 3: 5
# 3: 4
# 3: 3
# 3: 2
# 3: 1
# 5: 5
# 5: 4
# 5: 3
# 5: 2
# 5: 1
# 2: 5
# 2: 4
# 2: 3
# 2: 2
# 2: 1
# 4: 5
# 4: 4
# 4: 3
# 6: 5
# 6: 4
# 6: 3
# 6: 2
# 6: 1
# 4: 2
# 4: 1
5.バックグラウンドスレッド(daemon)
バックグラウンド以外のすべてのスレッドが終了すると、スレッドは終了します.例えば、ある時点でスレッドがsleepになり、プログラムが終了します.
package com.sam.thread;
public class DaemonThread extends Thread {
private int countDown = 5;
private static int threadCount = 0;
public DaemonThread() {
super(" " + ++threadCount); // store the thread name
setDaemon(true);
start();
}
public String toString() {
return "#" + getName() + ": " + countDown;
}
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
try {
sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new DaemonThread();
}
}
}
結果:
# 1: 5
# 3: 5
# 5: 5
# 4: 5
# 2: 5
6.join()とinterrupt()
package com.sam.thread;
class A extends Thread {
public A() {
start();
}
public void run() {
try {
System.out.println("A started.");
sleep(1000);
} catch (InterruptedException e) {
System.out.println("Sleep interrupted");
}
}
}
public class JoinThread extends Thread {
A a;
public JoinThread(A a) {
this.a = a;
start();
}
public void run() {
try {
a.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("JoinThread started.");
}
public static void main(String[] args) {
A a = new A();
JoinThread jt = new JoinThread(a);
a.interrupt();
}
}
結果:
A started.
Sleep interrupted
JoinThread started.
7.Runnableインタフェース
package com.sam.thread;
public class RunnableThread implements Runnable {
private int countDown = 5;
public String toString() {
return "#" + Thread.currentThread().getName() + ": " + countDown;
}
@Override
public void run() {
while (true) {
System.out.println(this);
if (--countDown == 0)
return;
}
}
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
new Thread(new RunnableThread(), "" + i).start();
}
}
}
runnableインタフェース自体はスレッドの特性を持たず、実行するか、個別のThreadオブジェクトを作成します.
8.リソースへの不正アクセス
package com.sam.thread;
public class AlwaysEven {
int i;
void next() {
i++;
i++;
}
int get() {
return i;
}
public static void main(String[] args) {
final AlwaysEven ae = new AlwaysEven();
new Thread() {
public void run() {
while (true) {
int j = ae.get();
if (j % 2 != 0) {
System.out.println(j);
System.exit(0);
}
}
}
}.start();
while (true) {
ae.next();
}
}
}
結果:
1501
9.共有リソース競合の解決
共有リソースにアクセスする各メソッドにsynchronizedを追加する必要があります.そうしないと、追加しないメソッドはロックを無視します.
package com.sam.thread;
public class AlwaysEven {
int i;
synchronized void next() {
i++;
i++;
}
synchronized int get() {
return i;
}
public static void main(String[] args) {
final AlwaysEven ae = new AlwaysEven();
new Thread() {
public void run() {
while (true) {
int j = ae.get();
if (j % 2 != 0) {
System.out.println(j);
System.exit(0);
}
}
}
}.start();
while (true) {
ae.next();
}
}
}
10. volatile
コンパイラの最適化は禁止され、スレッドはオブジェクトのプライベートコピーを保持できず、効率に影響します.
11.臨界領域
複数のスレッドアクセスメソッドの一部のコードを防止します.
synchronized(syncObject) {
// This code can only be access
// by one thread at a time
}
12.スレッドの状態
新規(new)
準備完了(Runnable)
死亡(Dead)
ブロッキング(Blocked)
13. notify()
wait()のスレッドを起動します.
zz