zoukankan      html  css  js  c++  java
  • Java笔记(二)

    10. 

      public  protected default private
    同一个类中
    同一个包中  
    子类    
    不同包中      

    11. 线程:

     static Thread currentThread():获取当前线程对象

     getName():获取线程名称

     设置线程名称:setName()或者构造函数

     创建线程的方式:

      1. 继承Thread类

        (1)定义类,继承Thread

        (2)复写Thread类中的void run()方法(因为Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码。该存储功能就是run方法。)

        (3)调用线程的start方法,该方法能启动线程,并能调用run方法

        注:对象.run()仅仅是对象调用方法。而线程创建了,并没有运行;

          对象.start()开启线程并执行该线程的run方法

      2. 实现Runnable接口

        (1)定义类,实现Runnable接口

        (2)覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中

        (3)通过Thread类建立线程对象

        (4)将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。因为,自定义的run方法所属的对象是Runnable接口的子类对象,所以要让线程去执行指定对象的run方法,就必须明确该run方法所属的对象。

        (5)调用Thread类的start方法开启线程,并调用Runnable接口子类的run方法

      实现方式与继承方式的区别:

       实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。

       继承Thread:线程代码存放在Thread子类run方法中;实现Runnable:线程代码存放在接口的子类的run方法。

     同步函数的锁是this;静态同步函数的锁是Class对象(类名.class)

     死锁:例:

     1 class DeadLock implements Runnable{
     2     private boolean flag;
     3     DeadLock(boolean flag){
     4         this.flag = flag;
     5     }
     6     public void run(){
     7         if(flag){
     8             while(true){
     9                 synchronized(Lock.locka){
    10                     System.out.println("if locka");
    11                     synchronized(Lock.lockb){
    12                         System.out.println("if lockb");
    13                     }
    14                 }
    15             }
    16         }
    17         else{
    18             while(true){
    19                 synchronized(Lock.lockb){
    20                     System.out.println("else lockb");
    21                     synchronized(Lock.locka){
    22                         System.out.println("else locka");
    23                     }
    24                 }
    25             }    
    26         }    
    27     }
    28 }
    29 
    30 class Lock{
    31     public static Object locka = new Object();
    32     public static Object lockb = new Object();
    33 }
    34 
    35 public class Demo{
    36     public static void main(String[] args) {
    37         Thread t1 = new Thread(new DeadLock(true));
    38         Thread t2 = new Thread(new DeadLock(false));
    39         t1.start();
    40         t2.start();
    41     }
    42 }

     wait()  notify()  notifyAll():

      都使用在同步中,因为要对持有监视器(锁)的线程操作,只有同步才具有锁。

      这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁。只有同一个锁上的被等待线程,可以被同一个锁上的notify()唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被对象调用的方法定义Object类中。

      生产者-消费者问题:

     1 class Resource{
     2     private String name;
     3     private int count = 1;
     4     private boolean flag = false;
     5     
     6     public synchronized void set(String name){
     7         while(flag){
     8             try {
     9                 this.wait();
    10             } catch (InterruptedException e) {
    11                 e.printStackTrace();
    12             }
    13         }
    14         this.name = name + " ~~ " + count++;
    15         System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);
    16         flag = true;
    17         this.notifyAll();
    18     }
    19     
    20     public synchronized void out(){
    21         while(!flag){
    22             try {
    23                 this.wait();
    24             } catch (InterruptedException e) {
    25                 e.printStackTrace();
    26             }
    27         }
    28         System.out.println(Thread.currentThread().getName() + "....消费者...." + this.name);
    29         flag = false;
    30         this.notifyAll();
    31     }
    32 }
    33 
    34 class Producer implements Runnable{
    35     private Resource r;
    36     Producer(Resource r){
    37         this.r = r;
    38     }
    39     public void run(){
    40         while(true){
    41             r.set("商品");
    42         }
    43     }
    44 }
    45 
    46 class Consumer implements Runnable{
    47     private Resource r;
    48     Consumer(Resource r){
    49         this.r = r;
    50     }
    51     public void run(){
    52         while(true){
    53             r.out();
    54         }
    55     }
    56 }
    57 
    58 public class Demo{
    59     public static void main(String[] args) {
    60         Resource r = new Resource();
    61         Thread t1 = new Thread(new Producer(r));
    62         Thread t2 = new Thread(new Producer(r));
    63         Thread t3 = new Thread(new Consumer(r));
    64         Thread t4 = new Thread(new Consumer(r));
    65         t1.start();
    66         t2.start();
    67         t3.start();
    68         t4.start();
    69     }
    70 }

     对于多个生产者和消费者。定义while判断标记的原因:让被唤醒的线程再一次判断标记。

                 定义notifyAll的原因:需要唤醒对方线程。如果只用notify,容易                                        出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

    生产者-消费者(升级版):

     1 import java.util.concurrent.locks.Condition;
     2 import java.util.concurrent.locks.Lock;
     3 import java.util.concurrent.locks.ReentrantLock;
     4 
     5 class Resource{
     6     private String name;
     7     private int count = 1;
     8     private boolean flag = false;
     9     private Lock lock = new ReentrantLock();
    10     private Condition condition_pro = lock.newCondition();
    11     private Condition condition_con = lock.newCondition();
    12     
    13     public void set(String name) throws InterruptedException{
    14         lock.lock();
    15         try{
    16             while(flag){
    17                 condition_pro.await();
    18             }
    19             this.name = name + " ~~ " + count++;
    20             System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);
    21             flag = true;
    22             condition_con.signal();
    23         }finally{
    24             lock.unlock();
    25         }
    26     }
    27     
    28     public void out() throws InterruptedException{
    29         lock.lock();
    30         try{
    31             while(!flag){
    32                 condition_con.await();
    33             }
    34             System.out.println(Thread.currentThread().getName() + "....消费者...." + this.name);
    35             flag = false;
    36             condition_pro.signal();
    37         }finally{
    38             lock.unlock();
    39         }
    40     }
    41 }
    42 
    43 class Producer implements Runnable{
    44     private Resource r;
    45     Producer(Resource r){
    46         this.r = r;
    47     }
    48     public void run(){
    49         while(true){
    50             try {
    51                 r.set("商品");
    52             } catch (InterruptedException e) {
    53                 e.printStackTrace();
    54             }
    55         }
    56     }
    57 }
    58 
    59 class Consumer implements Runnable{
    60     private Resource r;
    61     Consumer(Resource r){
    62         this.r = r;
    63     }
    64     public void run(){
    65         while(true){
    66             try {
    67                 r.out();
    68             } catch (InterruptedException e) {
    69                 e.printStackTrace();
    70             }
    71         }
    72     }
    73 }
    74 
    75 public class Demo{
    76     public static void main(String[] args) {
    77         Resource r = new Resource();
    78         Thread t1 = new Thread(new Producer(r));
    79         Thread t2 = new Thread(new Producer(r));
    80         Thread t3 = new Thread(new Consumer(r));
    81         Thread t4 = new Thread(new Consumer(r));
    82         t1.start();
    83         t2.start();
    84         t3.start();
    85         t4.start();
    86     }
    87 }

     JDK1.5中提供了多线程升级解决方案。将同步Synchronized替换成Lock操作。将Object中的wait、notify、notifyAll替换成了Condition对象,该对象可以Lock锁进行获取。  

     如何停止线程:stop方法已经过时,只能让run方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。

     特殊情况:当线程处于冻结状态。就不会读取到标记,那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。

     Thread类提供该方法interrupt();

     1 class StopThread implements Runnable{
     2     private boolean flag = true;
     3     public synchronized void run(){
     4         while(flag){
     5             try{
     6                 wait();
     7             }catch(InterruptedException e){
     8                 System.out.println(Thread.currentThread().getName() + "...exception");
     9             }
    10             System.out.println(Thread.currentThread().getName() + "...run");
    11         }
    12     }
    13     public void changeFlag(){
    14         flag = false;
    15     }
    16 }
    17 
    18 public class Demo{
    19     public static void main(String[] args) {
    20         StopThread st = new StopThread();
    21         Thread t1 = new Thread(st);
    22         Thread t2 = new Thread(st);
    23         t1.start();
    24         t2.start();
    25         
    26         int num = 0;
    27         while(true){
    28             if(num++ == 60){
    29                 t1.interrupt();
    30                 t2.interrupt();
    31                 st.changeFlag();
    32                 break;
    33             }
    34             System.out.println(Thread.currentThread().getName() + "....." + num);
    35         }
    36         System.out.println("over");
    37     }
    38 }

    输出结果:

    ...
    ...
    main.....59
    main.....60
    over
    Thread-0...exception
    Thread-0...run
    Thread-1...exception
    Thread-1...run

     守护线程:即后台线程。线程对象.setDaemon(true)

     当正在运行的线程都是守护线程时(即前台线程全结束),JVM退出。该方法必须在启动线程前调用。

     Join方法:线程对象.join(),当A线程执行到了B线程的.join()方法,A就会等待。等B线程都执行完,A才会执行。join可以用来临时加入线程执行。

     yield方法:暂停当前正在执行的线程对象,并执行其他线程。

  • 相关阅读:
    新概念英语第四册16-30课(转)
    新概念英语第四册01-15课(转)
    通过了解MySpace的六次重构经历,来认识分布式系统到底该如何创建(转载)
    BASE64编码规则及C#实现
    Lucene资料汇总
    SQL Server性能监控
    Fedex接口和测试账户
    css语法
    POI操作Excel常用方法总结 (转)
    java eclipse中的代码联动提示功能
  • 原文地址:https://www.cnblogs.com/zhangtianq/p/6286434.html
Copyright © 2011-2022 走看看