Java并发/多线程

Java多线程

实现线程的两种方法:

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

你可能感兴趣的:(java并发)