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 }
原文地址:https://www.cnblogs.com/Terminaling/p/4072359.html