1、线程的方法:
(1)后台线程:调用setDaemon(true)设置,要在start()之前调用
package thirdDay; class childDaemon implements Runnable { public void run() { while(true) { System.out.println("thread is running"); } } } public class setDaemon { public static void main(String args[]) { childDaemon c=new childDaemon();//定义一个类 Thread cc=new Thread(c);//定义一个线程,将类赋给这个线程 cc.setDaemon(true);//设置为后台线程 cc.start();//线程启动 //程序的运行结果:在主线程结束之前就退出了,只运行了几行循环; //说明它是后台线程; } }(2)线程的强制执行:join
通过join就可以在一个线程里强制执行这个线程;
class joinThread1 implements Runnable { public void run() { for(int i=0;i<1;i++) System.out.println(Thread.currentThread().getName()+"-->>"+i); } } public class joinThread { public static void main(String[] args) { // TODO Auto-generated method stub Thread t=new Thread(new joinThread1()); t.start();//此时启动线程,但是不知道什么时候执行 for(int i=0;i<5;i++) { if(i==2) try { t.join();//强制执行,在第2次的时候 } catch(Exception e) { e.getMessage(); } System.out.println("Main is running"); } } } /*下面是运行结果: Main is running Main is running Thread-0-->>0 Main is running Main is running Main is running */(3)线程的休眠:sleep
a、休眠线程可以被另一个线程终止,然后抛出异常;
b、休眠是静态方法,用Thread.sleep(200)调用;那么如何判断是哪个线程休眠:很简单,在哪个线程调用,就是哪个线程休眠;
package thirdDay; class threadSleep extends Thread { public void run() { loop(); } public void loop() { String name=Thread.currentThread().getName(); System.out.println(name+"---->>刚进入loop方法"); for(int i=0;i<5;i++) { try { Thread.sleep(500); } catch(InterruptedException x) {} System.out.println("name="+name); } System.out.println(name+"---->>离开loop方法"); } } public class sleepThread { public static void main(String[] args) { threadSleep tt=new threadSleep(); tt.setName("my worker thread"); tt.start();//start就是启动一个新线程,然后调用run,调用loop try { Thread.sleep(500);//主线程等待,使得tt线程可以执行一部分; } catch(InterruptedException x)//线程如果被中断,就会抛出异常; {} tt.loop();//主线程调用了loop方法,虽然主体是tt线程,但是却是主线程main在执行loop; } } /*下面是运行结果 my worker thread---->>刚进入loop方法 name=my worker thread main---->>刚进入loop方法 name=main name=my worker thread name=main name=my worker thread name=main name=my worker thread name=my worker thread name=main my worker thread---->>离开loop方法 name=main main---->>离开loop方法 */(4)线程的中断:interrupted
package thirdDay; public class interruptedThread { public static void main(String[] args) { Thread t=Thread.currentThread();//此时t为主线程main System.out.println("A:t.isInterrupted="+t.isInterrupted());//输出true t.interrupt();//main线程被中断 System.out.println("B:t.isInterrupted="+t.isInterrupted());//输出false System.out.println("C:t.isInterrupted="+t.isInterrupted());//输出false try//进入不了try,因为线程被中断 { Thread.sleep(500); System.out.println("线程没有被中断"); } catch(InterruptedException x)//main被中断,抛出异常,执行下面的代码 { System.out.println("线程被中断"); } //因为sleep已经抛出了异常,所以它清除了中断标志 System.out.println("D:t.isInterrupted="+t.isInterrupted());//输出true } } /*下面是输出结果: A:t.isInterrupted=false B:t.isInterrupted=true C:t.isInterrupted=true 线程被中断 D:t.isInterrupted=false */2、线程的同步:
(1)同步代码块:
在前面的卖票程序中,有可能同一张票打印两次或多次,也有可能打印的为0;
解决办法:
class TestThread implements Runnable { private int tickets=20; public void run() { while(true) { synchronized(this) { if(tickets>0) { try { Thread.sleep(200);//加一个sleep,以让出cpu给其他的线程; //不然这个同步代码会一直循环执行,别的线程还没创建这个线程就已经执行完了 } catch(Exception e){} System.out.println(Thread.currentThread().getName()+"出售票"+tickets--); } } } } } public class synchronize { public static void main(String[] args) { TestThread t=new TestThread(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } }
(2)同步方法:
跟代码块一样,就是把代码块封装到函数中;
package thirdDay; class TestThread1 implements Runnable { private int tickets=20; public void run() { while(true){ sale();//这个while写在run里面,不能写在synchronized方法中 } //否则会一直在while里面,跳不出去,因为synchronized方法 //只有里面的线程执行完后才会跳出来 } public synchronized void sale() { if(tickets>0) { try { Thread.sleep(300); } catch(Exception e){} System.out.println(Thread.currentThread().getName()+"出售票"+ tickets--); } } } public class synchronize2 { public static void main(String[] args) { TestThread1 t=new TestThread1(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } }
3、关于线程的消费者和生产者模式:
package thirdDay; import java.util.LinkedList; /* *仓库类storage实现缓冲区 */ class storage { //定义一个最大存货量 private final int MaxSize=100; //定义一个存货载体,就是一个变量代表存了多少货 private LinkedList<Object> list=new LinkedList<Object>(); //生产的num个数 public void produe(int num) { //同步代码段 synchronized(list) { //如果仓库的容量不足:list.size()仓库内目前有多少存货 while(list.size()+num>MaxSize) { System.out.println("要生产的产品数量:"+num+"/t目前存货量:"+ list.size()+"/t暂时不能执行生产任务!"); try { //由于仓库的容量不足,所以阻塞生产 list.wait(); } catch(InterruptedException e) { e.printStackTrace(); } } //如果生产条件满足,就生产num个产品 for(int i=1;i<=num;i++) { list.add(new Object()); } System.out.println("已经生产的产品数量:"+num+"/t目前存货量"+ list.size()); //给其他等待的线程发出通知,同时自己放弃锁,处于等待状态; list.notifyAll(); } } //消费num个产品 public void consum(int num) { //同步代码段 synchronized(list) { //如果要消费的大于库存量 while(list.size()<num) { System.out.println("要消费的产品数量:"+num+"/t库存量:"+ list.size()+"/t暂时不能执行生产任务"); try { //由于条件不满足,消费阻塞 list.wait(); } catch(InterruptedException e) { e.printStackTrace(); } } //条件满足,消费num个产品 for(int i=1;i<=num;i++) { list.remove(); } System.out.println("已经消费产品数:"+num+"/t剩余库存数:"+list.size()); list.notifyAll(); } } //get和set方法 public LinkedList<Object> getList() { return list; } public void setList(LinkedList<Object> list) { this.list=list; } public int getMaxSize() { return MaxSize; } } //生产者类Producer继承Thread class Producer extends Thread { //生产数量 private int num; //产品所要放置的仓库 private storage storage; //构造函数,设置仓库 public Producer(storage storage) { this.storage=storage; } //线程run函数 public void run() { produce(num); } //调用仓库的生产函数 public void produce(int num) { storage.produe(num); } //get和set方法 public int getNum() { return num; } public void setNum(int num) { this.num=num; } public storage getStorage() { return storage; } public void setStorage(storage storage) { this.storage=storage; } } //消费者类Consumer继承自Thread class Consumer extends Thread { //消费数量 private int num; //产品所要放置的仓库 private storage storage; //构造函数,设置仓库 public Consumer(storage storage) { this.storage=storage; } //线程run函数 public void run() { consum(num); } //调用仓库的消费函数 public void consum(int num) { storage.consum(num); } //get和set方法 public int getNum() { return num; } public void setNum(int num) { this.num=num; } public storage getStorage() { return storage; } public void setStorage(storage storage) { this.storage=storage; } } //测试类主程序 public class produceAndConsum { public static void main(String[] args) { //仓库对象 storage storage=new storage(); //生产者对象 Producer p1=new Producer(storage); Producer p2=new Producer(storage); Producer p3=new Producer(storage); Producer p4=new Producer(storage); Producer p5=new Producer(storage); Producer p6=new Producer(storage); //消费者对象 Consumer c1=new Consumer(storage); Consumer c2=new Consumer(storage); Consumer c3=new Consumer(storage); //设置生产的产品的数量 p1.setNum(10); p2.setNum(20); p3.setNum(30); p4.setNum(10); p5.setNum(20); p6.setNum(30); //设置消费的产品的数量 c1.setNum(10); c2.setNum(20); c3.setNum(30); //线程开始执行 c1.start(); c2.start(); c3.start(); p1.start(); p2.start(); p3.start(); } }