首页 > 代码库 > java学习-线程

java学习-线程

由于自己最近接手一个项目,构思过程中,线程可能会用的较多,所以今天翻出来把线程这块好好复习一下,以下是一点学习总结。分享写的比较拙略,只为自己笔记。为自己以后存储参考资源而已。
  pass:(被重写的方法不能跑一个比父类更大的异常)

 

 

创建于一个继承thread的子类:

 1 class testThread extends Thread{ 2     public void Run(){//新建一个线程里的run方法,实现此子线程需要完成的功能 3         for(int i = 0;i < 100;i++){ 4             Thread.currentThread().sleep(1000); 5             System.out.println(Thread.currentThread().getName()+":"+i); 6         } 7     } 8 } 9 public class TestThread{10    static void main(String arg[]){11       testThread sT1 = new testThread();12       testThread sT2 = new testThread();//创建一个子类的对象13       sT1.setName("线程1:");14       sT1.setpriority(Thread.MAX.PRIORITY);15       sT1.start();16       sT2.setName("线程2:");17       sT2.start();18       //调用线程的start方法,启动此线程,调用相应的run方法,19       //一个线程只能执行一次start,具体请见jdk手册。20       //如果此处启用的是run方法,则不是双线程。必须是start方法。21    Thread.currentThread().setName("子线程:");22     for(int i = 0;i < 100;i++){23         System.out.println(Thread.currentThread().getName()+":"+Thread.currentThread().getPriority()+":"i);24         /*if(i % 10 == 0){25             Thread.currentThread().yield();26             27         }*/28         /*if(i % 10 ==0){29             try{30                 sT1.join();31             }catch(InterruptedException e){32                e.printStackTrace();33             }34         }*/35         }36         System.out.println(sT1.isAlive());/*返回FALSE*/37    }38 }

Thread常用方法:
1.start() 启动线程并执行相应的run方法。
2.run()  子线程要执行的代码放入其中,一般都是被重写。
3.currentThread() 静态的,调取当前的线程
4.getName() 获取当前线程的名字
5.setName() 设置子线程的名字
6.yield()  线程释放当前cpu的执行权
7.join() 在a线程中调用b线程的join方法,表示,当执行到此方法,a线程停止,直至b线程全部结束,a线程才继续执行
8.isAlive() 判断当前线程是否还存活
9.sleep(long l) 显示的当前线程睡眠1毫秒
10.设置线程的优先级:getpriority() 返回线程优先级;setpriority(int newpriority)改变线程的优先级

 1 /* 2   创建两个子线程,让其中一个输出1-100之间的偶数,另一个输出1-100之间的奇数 3 */ 4 class SubThread1 extends Thread{ 5     public void Run(){ 6         for (int i = 1; i < 100;i++){ 7             if(i % 2 == 0){ 8                 System.out.println(Thread.currentThread().getName()+":"+i); 9             }10         }11     }12 }13 class SubThread2 extends Thread{14     public void Run(){15         for (int i = 1; i < 100;i++){16             if(i % 2 != 0){17                 System.out.println(Thread.currentThread().getName()+":"+i);18             }19         }20     }21 }22     public class TestThread{23             public static void main(String[] args) {24                  SubThread sT1 = new SubThread1();25                   SubThread sT2 = new SubThread();26                   //sT1.start();27                   //sT2.start();28                   //继承于Thread类的匿名对象29                   new Thread(){30                     public void Run(){31                      for (int i = 1; i < 100;i++){32                        if(i % 2 != 0){33                          System.out.println(Thread.currentThread().getName()+":"+i);34             }35         }36     }}.start();37                  new Thread(){38                     public void Run(){39                      for (int i = 1; i < 100;i++){40                        if(i % 2 != 0){41                          System.out.println(Thread.currentThread().getName()+":"+i);42             }43         }44     }}.start();45 46             }47     }
 1 /*模拟火车站首售票窗口,开启三个窗口售票.总票数为100张*/ 2  class Window extends Thread{ 3         static int tickets = 100;//声明为固定变量实现公用,限制只有一百张,但声明周期很长 4          public void Run(){ 5              while(true){ 6                  if(tickets > 0){ 7                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--); 8                  }else{ 9                      break;//退出10                  }11              }12          }13  }14  public class TestWindow{15 16  }17 18  public static void main(String[] args) {19      Window W1 = new Window();20      Window W2 = new Window();21      Window W3 = new Window();22 23      W1.setName("窗口1:");24      W2.setName("窗口2:");25      W3.setName("窗口3:");26 27      W1.start();28      W2.start();29      w3.start();30  }

第二种方式-实现:

//1.创建一个实现了runable的类 class PrintNum1 implements Runable{    public void run(){//实现接口的抽象方法         for (int i = 1; i < 100;i++){                       if(i % 2 != 0){                         System.out.println(Thread.currentThread().getName()+":"+i);            }        }    }}public class TestWindow1{    public static void main(String[] args) {        //2.创建一个runable接口的实现对象        PrintNum1 p = new PrintNum1();        //要想启动一个多线程,必须调用start方法        //3.将此对象作为形参传递给Thread类的构造器中,创建Thread类的对象,此对象即为一个线程。        Thread T1 = new Thread(p);//构造一个Thread对象        T1.start();         //启动线程,执行Thread对象生成时构造器形参的对象的Run方法        //4.在创建一个线程        Thread T2 = new Thread(p);//构造一个Thread对象        T2.start();    } }

实现的方式实现多窗口售票 存在线程的安全问题
为何会出现程序的安全问题?
由于一个线程在操作共享数据的执行过程中未执行完的情况下,另外的线程参与进来,导致共享数据存在安全问题
如何解决?
必须让一个操作共享数据完毕之后,其他线程才有机会共享数据的操作。
java如何实现线程安全?
线程的同步:1.同步代码块 synchronized(同步监视器){
    需要同步的代码块(操作数据共享的代码)
}
共享数据:多个线程共同操作的一个数据
同步监视器:由任何一个类的对象来充当,那个线程获取此监视器,谁就执行大括号里面的代码 俗称:锁
在实现的方式中考虑同步的话可以考虑this来充当锁,但在继承当中需要慎重.

 1 class Window1 implements Thread{ 2     int ticket = 100;//共享数据 3     static Object object = new Object(); 4     public void run(){ 5         //Object object = new Object();不能在此处写,这样会导致引发三次局部变量 6         while(true){ 7             synchronized(object){//此处可以为this,代表当前的对象W1 8                  if(tickets > 0){ 9                      try{//这个地方会出现重票和错票10 11                         Thread.currentThread().sleep(10);//让其休眠10毫秒12                      }catch(InterruptedException e){13                        e.printStackTrace();14                      }15                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);16                  }else{17                      break;//退出18              }19          }20           }21     }22 }23 public class TestWindow1{24   public static void main(String[] args) {25       Window1 W1 = new Window1();26       Thread t1 = new Thread(W1);27       Thread t2 = new Thread(W1);28     /*只new了一个w对象,三个线程共享*/29       t1.setName("窗口1:");30      t2.setName("窗口2:");31      32       t1.start();33   //共享同一个W对像34       35       t2.start();36 37   }38 39 }
 1 /*实现改进版售票器*/ 2 class Window1 implements Thread{ 3     int ticket = 100; 4     public void run(){ 5         while(true){ 6                  if(tickets > 0){ 7                      /*try{//这个地方会出现重票和错票 8     9                         Thread.currentThread().sleep(10);//让其休眠10毫秒10                      }catch(InterruptedException e){11                        e.printStackTrace();12                      }*/13                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);14                  }else{15                      break;//退出16              }17           }18     }19 }20 public class TestWindow1{21   public static void main(String[] args) {22       Window1 W1 = new Window1();23       Thread t1 = new Thread(W1);24       Thread t2 = new Thread(W1);25     /*只new了一个w对象,三个线程共享*/26       t1.setName("窗口1:");27      t2.setName("窗口2:");28      29       t1.start();30   //共享同一个W对像31       32       t2.start();33 34   }

同步方法
将操作共享数据的方法声明为synchronized,
即此方法为同步方法,能够保证当其中一个线程执行此方法时,
其他线程在外等待直到此线程执行完此方法
>同步方法的锁是当前对象:this
线程的弊端:同一个时间只有一个线程访问共享数据,效率变低了。

 

 

 1 /*实现改进版售票器*/ 2 class Window1 implements Thread{ 3     int ticket = 100; 4     public void run(){ 5         while(true){ 6         show(); 7  8         } 9     }10     public synchronized void show(){11     12                  if(tickets > 0){13                      try{//这个地方会出现重票和错票14                         Thread.currentThread().sleep(10);//让其休眠10毫秒15                      }catch(InterruptedException e){16                        e.printStackTrace();17                      }18                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);19                  }else{20                      break;//退出21              22           }23     }24 }25 public class TestWindow1{26   public static void main(String[] args) {27       Window1 W1 = new Window1();28       Thread t1 = new Thread(W1);29       Thread t2 = new Thread(W1);30     /*只new了一个w对象,三个线程共享*/31       t1.setName("窗口1:");32      t2.setName("窗口2:");33      34       t1.start();35   //共享同一个W对像36       37       t2.start();38 39   }
 1 /*继承实现同步方法*/ 2 class Window extends Thread{ 3         static int tickets = 100;//声明为固定变量实现公用,限制只有一百张,但声明周期很长 4         static Object o = new Object(); 5          public void Run(){ 6              while(true){ 7                  synchronized(o){ 8                  if(tickets > 0){ 9                      System.out.println(Thread.currentThread().getName()+"售票.票号为:"+ tickets--);10                  }else{11                      break;//退出12                  }13                }14              }15          }16  }17  public class TestWindow{18  public static void main(String[] args) {19      Window W1 = new Window();20      Window W2 = new Window();21      Window W3 = new Window();22 23      W1.setName("窗口1:");24      W2.setName("窗口2:");25      W3.setName("窗口3:");26 27      W1.start();28      W2.start();29      w3.start();30  }31 }
/*懒汉模式-单例模式sleep()和yield()不会释放锁的,static方法里面锁不能写this,使用当前类本身充当*/class  Singleton{   private Singleton(){   }   private static Singleton instance = null;   public static Singleton getInstance(){       if(instance == null){       synchronized(Singleton.class){       if(instance == null){           instance = new Singleton();       }       }       }       return instance;   } } public class TestSingleton{  public static void main(String[] args) {      Singleton s1 = new Singleton.getInstance();      Singleton s2 = new Singleton.getInstance();      System.out.println(s1 == s2);//判断两个对象相等,只能用==  } }
 1 /*银行存钱问题 2 */ 3 class Count{ 4     double balance;//余额 5     public Account(){ 6  7     }     8     public synchronized void despoit(double amt){//存钱 9       notify();//实现二者交替打印10       balance += amt;11       try{12           Thread.currentThread().sleep(10);13       }14       catch(InterruptedException e){15             e.printStackTrace();16       }17       System.out.println(Thread.currentThread().getName()+":"+balance);18       wait();19     }20 21 }22 class Customer extends Thread{23     Account account;24     public Customer(Account account){25         this.account = account;26     }27     public void run(){28        for(int i = 0;i<3;i++){29            account.despoit(1000);30        }31     }32 }33 public class TestAccount{34    public static void main(String[] args) {35        Account acct =new Account();36        Customer c1 = new Customer(acct);37        Customer c2 = new Customer(acct);38        Customer c3 = new Customer(acct);39 40        c1.setName("1");41        c2.setName("2");42        c3.setName("3");43 44        c1.start();45        c2.start();46        c3.start();47    }48 }
 1 /*死锁问题--处理线程同步时容易出现 2 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的资源,就形成了线程的死锁*/ 3  public class TestDeadLock{ 4      static StringBuffer sb1 = new StringBuffer(); 5      static StringBuffer sb2 = new StringBuffer(); 6  7      public static void main(String[] args) { 8          new Thread(){ 9               public void run(){10                synchronized(sb1){11                 try{12                     Thread.currentThread().sleep(10);13                   }14                    catch(InterruptedException e){15                      e.printStackTrace();16                   }17                 sb1.append("A");18                   synchronized(sb2){19                     sb2.append("B");20                      System.out.println(sb1);21                      System.out.println(sb2);22                    }23                 }24               }25          }.start();26 27          new Thread(){28              public void run(){29                synchronized(sb1){30                    try{31                     Thread.currentThread().sleep(10);32                   }33                    catch(InterruptedException e){34                      e.printStackTrace();35                   }36                 sb1.append("C");37                   synchronized(sb2){38                     sb2.append("D");39                     System.out.println(sb1);40                      System.out.println(sb2);41                    }42                 }43              }44          }.start();45      }46  } 
/*Deadlock.java*/class A{    public synchronized void foo(B b){        System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了A实例的foo方法");        try{            Thread.sleep(200)        }catch(InterruptedException e){            e.printStackTrace();        }        System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用b的last方法");    }    public synchronized void Last(){        System.out.println("进入了A的last方发出内部");    }}class B{   public synchronized void bar(A a){     System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入了B实例的bar方法");try{            Thread.sleep(200)        }catch(InterruptedException e){            e.printStackTrace();        }        System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用A的last方法");    }    public synchronized void Last(){        System.out.println("进入了B的last方发出内部");    }}public class Deadlock implements Runable{    A a = new A();    B b = new B();    public void init(){        Thread.currentThread.setName("主线程");        //调用a对象的foo方法        a.foo(b);        System.out.println("进入了主线程之后");    }    public void run(){        Thread.currentThread.setName("副线程");       //调用b对象的bar方法        b.bar(a);        System.out.println("进入了副线程之后");    }    public static void main(String[] args) {        Deadlock d1 = new Deadlock();        new Thread(d1).start();//启动run方法        d1.init();    }}

线程通信
1.wait()方法:令当前线程挂起并放弃CPU,同步资源,使别的线程可访问并修改资源,而当前线程排队等候再次对资源的访问
2.notify()方法:唤醒正在排队等待同步资源的线程中优先级最高的
3.notifyAll()方法:唤醒正在等待资源的所有线程结束等待
java.lang.Object提供的这三个方法只有在synchronized方法中或synchronized代码块中才能使用,否则会报错
线程通信:

 1 打印1-100,线程1,线程2交替打印*/ 2 class PrintNum implements Runable{ 3     int num = 1; 4        public void run(){ 5             6            while(true){ 7             synchronized(this){ 8                 notify(); 9                if(num<100){10                    try{Thread.currentThread().sleep(10);11                    }catch(InterruptedException e){12                      e.printStackTrace();13                    }14                    System.out.println(Thread.currentThread().getName()+":"+num);15                    num++;16                }else{17                    break;18              }19              wait();20          }21            }22        }23 }24 25 public class TestCommunication{26     public static void main(String[] args) {27         PrintNum p = new PrintNum();28         Thread t1 = new Thread(p);29         Thread t2 = new Thread(p);30 31         t1.setName("甲");32         t1.setName("乙");33 34         t1.start();35         t2.start();36     }37 38 }

生产者、消费者问题
多线程:消费者/生产者
共享数据:产品数量


 

 1 class Clerk{//店员 2     int product; 3  4     public synchronized void addProduct(){//生产产品 5         if(product >= 20){ 6             wait(); 7         }else{ 8             product++; 9             System.out.println(Thread.currentThread().getName()+":生产了第"+ product +"个");10             notifyall();11         }12 13     }14     public synchronized void consumeProduct(){//消费产品15         if(product <= 0){16             wait();17         }else{18             System.out.println(Thread.currentThread().getName()+"消费了第"+product +"个");19             product--;20             notifyall();21         }22     }23 }24 class Producer implements Thread{//生产者25     Clerk clerk;26 27     public Producer(Clerk clerk){28         this.clerk = clerk;29     }30     public void run(){31         System.out.println("生产者开始生产产品。");32         while(true){33             try{ 34                 Thread.currentThread().sleep(10);35                    }catch(InterruptedException e)36                    {37                      e.printStackTrace();38                    }39             clerk.addProduct();40         }41     }42 43 }44 class Consumer implements Runable{//消费者45      Clerk clerk;46      public Consumer(Clerk clerk){47          this.clerk = clerk;48      }49      public void run(){50          System.out.println("消费者开始消费产品。");51          while(true){52             try{53                 Thread.currentThread().sleep(10);54                    }catch(InterruptedException e) 55                    {56                      e.printStackTrace();57                    }58              clerk.consumeProduct();59          }60      }61 }

 

java学习-线程