主线程等待子线程的多种方法
synchronized浅析
sleep 是静态方法,Thread.sleep(xx)谁调用谁睡眠。
join 是合并方法。当前线程调用其它线程xx.join()则等到xx结束才干运行
yield 当前线程让出cpu进入就绪队列。
wait,noitfy,synchronized配合使用对资源进行管理。
synchronized(this)以及非static的synchronized方法(至于static synchronized方法请往下看),仅仅能防止多个线程同一时候运行同一个对象的同步代码段
Sleep
package cn.galc.test;
import java.util.*;
public class TestThread3 {
public static void main(String args[]){
MyThread thread = new MyThread();
thread.start();//调用start()方法启动新开辟的线程
try {
/*Thread.sleep(10000);
sleep()方法是在Thread类里面声明的一个静态方法。因此能够使用Thread.sleep()的格式进行调用
*/
/*MyThread.sleep(10000);
MyThread类继承了Thread类。自然也继承了sleep()方法,所以也能够使用MyThread.sleep()的格式进行调用
*/
/*静态方法的调用能够直接使用“类名.静态方法名”
或者“对象的引用.静态方法名”的方式来调用*/
MyThread.sleep(10000);
System.out.println("主线程睡眠了10秒种后再次启动了");
//在main()方法里面调用另外一个类的静态方法时,须要使用“静态方法所在的类.静态方法名”这种方式来调用
/*
所以这里是让主线程睡眠10秒种
在哪个线程里面调用了sleep()方法就让哪个线程睡眠,所以如今是主线程睡眠了。
*/
} catch (InterruptedException e) {
e.printStackTrace();
}
//thread.interrupt();//使用interrupt()方法去结束掉一个线程的运行并非一个非常好的做法
thread.flag=false;//改变循环条件,结束死循环
/**
* 当发生InterruptedException时。直接把循环的条件设置为false就可以退出死循环,
* 继而结束掉子线程的运行。这是一种比較好的结束子线程的做法
*/
/**
* 调用interrupt()方法把正在运行的线程打断
相当于是主线程一盆凉水泼上去把正在运行分线程打断了
分线程被打断之后就会抛InterruptedException异常。这样就会运行return语句返回。结束掉线程的运行
所以这里的分线程在运行完10秒钟之后就结束掉了线程的运行
*/
}
}
class MyThread extends Thread {
boolean flag = true;// 定义一个标记。用来控制循环的条件
public void run() {
/*
* 注意:这里不能在run()方法的后面直接写throw Exception来抛异常,
* 由于如今是要重写从Thread类继承而来的run()方法,重写方法不能抛出比被重写的方法的不同的异常。
* 所以这里仅仅能写try……catch()来捕获异常
*/
while (flag) {
System.out.println("==========" + new Date().toLocaleString() + "===========");
try {
/*
* 静态方法的调用格式一般为“类名.方法名”的格式去调用 在本类中声明的静态方法时调用时直接写静态方法名就可以。 当然使用“类名.方法名”的格式去调用也是没有错的
*/
// MyThread.sleep(1000);//使用“类名.方法名”的格式去调用属于本类的静态方法
sleep(1000);//睡眠的时假设被打断就会抛出InterruptedException异常
// 这里是让这个新开辟的线程每隔一秒睡眠一次,然后睡眠一秒钟后再次启动该线程
// 这里在一个死循环里面每隔一秒启动一次线程,每一个一秒打印出当前的系统时间
} catch (InterruptedException e) {
/*
* 睡眠的时一盘冷水泼过来就有可能会打断睡眠
* 因此让正在运行线程被一些意外的原因中断的时候有可能会抛被打搅中断(InterruptedException)的异常
*/
return;
// 线程被中断后就返回。相当于是结束线程
}
}
}
}
join
package cn.galc.test;
public class TestThread4 {
public static void main(String args[]) {
MyThread2 thread2 = new MyThread2("mythread");
// 在创建一个新的线程对象的同一时候给这个线程对象命名为mythread
thread2.start();// 启动线程
try {
thread2.join();// 调用join()方法合并线程,将子线程mythread合并到主线程里面
// 合并线程后,程序的运行的过程就相当于是方法的调用的运行过程
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i <= 5; i++) {
System.out.println("I am main Thread");
}
}
}
class MyThread2 extends Thread {
MyThread2(String s) {
super(s);
/*
* 使用super关键字调用父类的构造方法
* 父类Thread的当中一个构造方法:“public Thread(String name)”
* 通过这种构造方法能够给新开辟的线程命名,便于管理线程
*/
}
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("I am a\t" + getName());
// 使用父类Thread里面定义的
//public final String getName(),Returns this thread's name.
try {
sleep(1000);// 让子线程每运行一次就睡眠1秒钟
} catch (InterruptedException e) {
return;
}
}
}
}
yield
package cn.galc.test;
public class TestThread5 {
public static void main(String args[]) {
MyThread3 t1 = new MyThread3("t1");
/* 同一时候开辟了两条子线程t1和t2。t1和t2运行的都是run()方法 */
/* 这个程序的运行过程中总共同拥有3个线程在并行运行,分别为子线程t1和t2以及主线程 */
MyThread3 t2 = new MyThread3("t2");
t1.start();// 启动子线程t1
t2.start();// 启动子线程t2
for (int i = 0; i <= 5; i++) {
System.out.println("I am main Thread");
}
}
}
class MyThread3 extends Thread {
MyThread3(String s) {
super(s);
}
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(getName() + ":" + i);
if (i % 2 == 0) {
yield();// 当运行到i能被2整除时当前运行的线程就让出来让还有一个在运行run()方法的线程来优先运行
/*
* 在程序的运行的过程中能够看到,
* 线程t1运行到(i%2==0)次时就会让出线程让t2线程来优先运行
* 而线程t2运行到(i%2==0)次时也会让出线程给t1线程优先运行
*/
}
}
}
}
生产者消费者(wait,notify)
import java.util.Random;
public class TestAbstract{
public static void main(String[] args) {
Thread [] C = new Thread[5];
Thread [] P = new Thread[5];
Stack stk = new Stack();
for(int i = 0;i<5;i++){
P[i] = new Thread(new Proceduce(stk));
P[i].setName("procedure "+i);
P[i].start();
C[i] = new Thread(new Consumer(stk));
C[i].setName("Consumer "+i);
C[i].start();
}
}
}
class Stack{
String table = "abcdefghijklmnopqrstuvwxyz1234567890";
private int cnt = 0;
private char [] data = new char[10];
// private Object cu = new Object();
// private Object po = new Object();
public synchronized void push(char ch){
System.out.println(Thread.currentThread().getName()+" stack'cnt is "+cnt+"");
while(cnt == data.length){
try {
System.out.println(Thread.currentThread().getName()+" must wait");
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
data[cnt++] = ch;
this.notify();
}
public synchronized char pop(){
System.out.println(Thread.currentThread().getName()+" stack'cnt is "+cnt+"");
while(cnt == 0){
try {
System.out.println(Thread.currentThread().getName()+" must wait");
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.notify();
return data[--cnt];
}
}
/**
*
* @author Administrator
*
*/
class Consumer implements Runnable{
private Stack stk = null;
public Consumer(Stack stk){
this.stk = stk;
}
@Override
public String toString() {
return "Consumer [name=" + Thread.currentThread().getName() + "]";
}
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i < 10;i++){
try {
System.out.println(Thread.currentThread().getName()+" get char "+stk.pop());
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/**
*
* @author Administrator
*
*/
class Proceduce implements Runnable{
private Stack stk = null;
private Random rdm = new Random();
public Proceduce(Stack stk) {
super();
this.stk = stk;
}
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i < 10;i++){
try {
stk.push( stk.table.charAt( rdm.nextInt( stk.table.length() ) ) );
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
多线程拨号通话
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class TestAbstract{
static String [] tele = null;
public static void main(String[] args) throws Exception {
System.out.println(System.getProperty("user.dir"));
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(".\\src\\tele.txt")));
ArrayList<String> list = new ArrayList<String>();
String tmp;
while((tmp = br.readLine())!=null){
list.add(tmp);
System.out.println(tmp);
}
tele = (String [])list.toArray(new String[0]);
for(String s:tele)
System.out.println(s);
list = null;
br.close();
//获取须要拨打的电话
//创建10个线程工作
ArrayList<Thread> tt = new ArrayList<Thread>();
for(int i = 0;i<10;i++){
Thread t = new Thread(new work());
t.setName("Thread "+(i+1));
t.start();
tt.add(t);
}
for(Thread t:tt){
t.join();
}
System.out.println("dial is done");
}
}
class work implements Runnable{
static boolean [] tag = null;
boolean flag;
public work(){
if(tag==null)//线程中止4种方法,这个最安全
tag = new boolean[TestAbstract.tele.length];
flag = true;
}
String dial(){
synchronized (work.class) {
for(int i = 0;i<tag.length;i++){
if(tag[i]==false){
tag[i] = true;
return TestAbstract.tele[i];
}
}
}
return null;
}
@Override
public void run() {
// TODO Auto-generated method stub
while(flag){
String str = dial();
if(str==null){
flag = false;
break;
}
System.out.println(Thread.currentThread().getName() + " start dial " + str);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " dial "+str+" success");
}
}
}
Semaphore
ref
public class asdf {
public static void main(String[] args) {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
// 仅仅能5个线程同一时候訪问
final Semaphore semp = new Semaphore(5);
// 模拟20个client訪问
for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// 获取许可
semp.acquire();
System.out.println("Accessing: " + NO);
Thread.sleep((long) (Math.random() * 10000));
// 訪问完后,释放
semp.release();
System.out.println("-----------------"+semp.availablePermits());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
exec.execute(run);
}
// 退出线程池
exec.shutdown();
}
}
測试整理
public class asdf {
/**
* 生产者消费者模型,通过对同一个对象操作来进行同步。
* 生产者之间,消费者之间。生产消费者间相互排斥
*/
static Object consumerObj = new Object();
static Object providerObj = new Object();
class Consumer implements Runnable {
@Override public void run() {
consumer();
}
void consumer() {
System.out.println(Thread.currentThread().getName() + " start");
// 对Data进行相互排斥 ,也能够进行Semaphore.require,release 或者Lock 或者AtomicBoolean
synchronized (Data.data) {
while (Data.data.isEmpty()) {
try {
System.out.println(
Thread.currentThread().getName() + " data is empty,wait seconds");
Data.data.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Data.data.notifyAll();
}
}
System.out.println(
Thread.currentThread().getName() + " Consumer data:" + Data.data.poll());
Data.data.notifyAll();
}
System.out.println(Thread.currentThread().getName() + " end");
}
}
class Provider implements Runnable {
@Override public void run() {
provider();
}
void provider() {
System.out.println(Thread.currentThread().getName() + " start");
synchronized (Data.data) {
while (Data.data.size() >= Data.dataLength) {
try {
System.out.println(
Thread.currentThread().getName() + " data is full,wait seconds");
Data.data.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Data.data.notifyAll();
}
}
int d = (int) (Math.random() * 1000);
Data.data.offer(d);
System.out.println(Thread.currentThread().getName() + " Provider data:" + d);
Data.data.notifyAll();
}
System.out.println(Thread.currentThread().getName() + " end");
}
}
static class Data {
static final Queue<Integer> data = new LinkedList<Integer>();
static final int dataLength = 10;
}
static int wr;
static int readCnt = 0;
static int writeCnt = 0;
Semaphore readerSemaphore = new Semaphore(1);
Semaphore writerSemaphore = new Semaphore(1);
Semaphore readCntSemaphore = new Semaphore(1);
Semaphore writeCntSemaphore = new Semaphore(1);
class Writer1 implements Runnable {
void writer(int num) {
try {
writerSemaphore.acquire();
wr = num;
System.out.println(Thread.currentThread().getName() + " write num:" + num);
Thread.sleep((long) (Math.random() * 1000));
writerSemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override public void run() {
writer((int) (Math.random() * 1000));
}
}
class Reader1 implements Runnable {
int reader() {
int ret = 0;
try {
readerSemaphore.acquire();
if (readCnt == 0)
writerSemaphore.acquire(); // 没有读者在读,则可能存在写者,因此在这里尝试获取锁
readCnt++;
readerSemaphore.release();
ret = wr;
System.out.println(Thread.currentThread().getName() + " read num:" + ret);
Thread.sleep((long) (Math.random() * 1000));
readerSemaphore.acquire();
readCnt--;
if (readCnt == 0)
writerSemaphore.release();
readerSemaphore.release();
return ret;
} catch (InterruptedException e) {
e.printStackTrace();
return ret;
}
}
@Override public void run() {
reader();
}
}
class Reader2 implements Runnable {
public int reader() {
int ret=0;
try {
readerSemaphore.acquire();
readCntSemaphore.acquire();
readCnt++;
if(readCnt == 1){
writerSemaphore.acquire();
}
readCntSemaphore.release();
readerSemaphore.release();
ret = wr;
System.out.println(Thread.currentThread().getName() + " read data:" + ret);
Thread.sleep((long) (Math.random() * 1000));
readCntSemaphore.acquire();
readCnt--;
if(readCnt == 0){
writerSemaphore.release(); // 读写相互排斥
}
readCntSemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
return ret;
}
@Override public void run() {
reader();
}
}
class Writer2 implements Runnable {
public void writer(int num) {
try {
writeCntSemaphore.acquire();
writeCnt++;
if(writeCnt == 1){
readerSemaphore.acquire(); // 读写相互排斥
}
writeCntSemaphore.release();
writerSemaphore.acquire();
wr = num;
System.out.println(Thread.currentThread().getName() + " write data:" + num);
Thread.sleep((long) (Math.random() * 1000));
writerSemaphore.release();
writeCntSemaphore.acquire();
writeCnt--;
if(writeCnt == 0){
readerSemaphore.release(); // 读写相互排斥
}
writeCntSemaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override public void run() {
writer((int) (Math.random() * 1000));
}
}
static void ProviderConsumerTest() {
// 线程池
ExecutorService exec = Executors.newCachedThreadPool();
asdf tt = new asdf();
for (int index = 0; index < 5; index++) {
Thread t = new Thread(tt.new Consumer());
t.setName("Consumer" + String.valueOf(index));
exec.execute(t);
}
for (int index = 0; index < 5; index++) {
Thread t = new Thread(tt.new Provider());
t.setName("Provider" + String.valueOf(index));
exec.execute(t);
}
// 退出线程池
exec.shutdown();
}
static void readerPriority() {
asdf tt = new asdf();
Random random = new Random();
random.setSeed(System.currentTimeMillis());
for (int i = 0; i < 20; i++) {
//随机生成读者和写者
if (random.nextBoolean()) {
Thread t = new Thread(tt.new Reader1());
t.start();
} else {
Thread t = new Thread(tt.new Writer1());
t.start();
}
}
}
static void writerPriority() {
asdf tt = new asdf();
Random random = new Random();
random.setSeed(System.currentTimeMillis());
for (int i = 0; i < 20; i++) {
//随机生成读者和写者
if (random.nextBoolean()) {
Thread t = new Thread(tt.new Reader2());
t.start();
} else {
Thread t = new Thread(tt.new Writer2());
t.start();
}
}
}
public static void main(String[] args) {
// 生产者消费者演示样例
// ProviderConsumerTest();
// 读者优先
// readerPriority();
// 写者优先
writerPriority();
}
}