zoukankan      html  css  js  c++  java
  • 基础知识《四》---Java多线程学习总结

    本文转载自51cto

    一、线程的基本概念
    简单的说:线程就是一个程序里不同的执行路径,在同一个时间点上cpu只会有一个线程在执行,Java里的多线程是通过java.lang.Thread类来实现的,每个线程都拥有自己独立的方法栈空间。

    二、java线程的创建和启动
    第一种
    定义线程类实现Runnable接口:
    Thread myThread = new Thread(target) //target为Runnable接口类型
    Runnable中只有一个方法:
    public void run();用以定义线程运行体
    第二种
    可以定义一个Thread的子类并重写其run方法:
    clas MyThread extends Thread{
    public void run(){}
    }
    线程类必须通过执行Thread的start()方法启动一个新的线程,如果调用run()方法是属于方法的调用,不会启动一个新的线程,推荐使用第一种方式创建线程,使用接口较为灵活。

    三、线程状态装换
    调用线程start()方法时,线程进入就绪状态,Cpu分配时间片,线程进入运行状态,时间片结束,run()方法未执行完,线程进入阻塞状态。

    四、线程控制基本方法
     isAlive() //判断线程是否还“活着”,即线程是否还未终止
    getPriority() //获得线程的优先级数值
    setPriority() //设置线程的优先级指数
    Thread.sleep() //静态方法,将当前线程睡眠指定毫秒数
    join()  //调用某线程的该方法,将当前线程与该线程合并,
    //即等待该线程结束,再回复当前线程的运行。
    yield()  //让出CPU,当前线程进入就绪状态等待调度
    interrupt() //中断线程
    wait()  //当前线程进入对象的wait pool
    notify()/notifyAll //唤醒对象的wait pool中的一个/所有等待线程

    五、sleep方法
    Thread的静态方法
    public static void sleep(long millis)throws InterruptedException
    必须对异常进行捕捉
    Thread.currentThread();  //拿到当前线程

    六、join和yield方法 

    t.join(); //t的run()方法完才会继续执行当前线程方法体
    //也就是两个线程变成了一个线程

    join方法的功能就是使异步执行的线程变成同步执行。也就是说,当调用线程实例的start方法后,这个方法会立即返回,如果在调用start方法后后需要使用一个由这个线程计算得到的值,就必须使用join方法。如果不使用join方法,就不能保证当执行到start方法后面的某条语句时,这个线程一定会执行完。

    下面的代码演示了join的用法。

     1 package mythread;  
     2  
     3 public class JoinThread extends Thread  
     4 {  
     5     public static int n = 0;  
     6  
     7     static synchronized void inc()  
     8     {  
     9         n++;  
    10     }  
    11     public void run()  
    12     {  
    13         for (int i = 0; i < 10; i++)  
    14             try 
    15             {  
    16                 inc();  
    17                 sleep(3);  // 为了使运行结果更随机,延迟3毫秒  
    18                   
    19             }  
    20             catch (Exception e)  
    21             {  
    22             }                                        
    23     }  
    24     public static void main(String[] args) throws Exception  
    25     {  
    26      
    27         Thread threads[] = new Thread[100];  
    28         for (int i = 0; i < threads.length; i++)  // 建立100个线程  
    29             threads[i] = new JoinThread();  
    30         for (int i = 0; i < threads.length; i++)   // 运行刚才建立的100个线程  
    31             threads[i].start();  
    32         if (args.length > 0)    
    33             for (int i = 0; i < threads.length; i++)   // 100个线程都执行完后继续  
    34                 threads[i].join();  
    35         System.out.println("n=" + JoinThread.n);  
    36     }  
    37 }  

    在例程2-8中建立了100个线程,每个线程使静态变量n增加10。如果在这100个线程都执行完后输出n,这个n值应该是1000。

    1.  测试1

    使用如下的命令运行上面程序:

    1. java mythread.JoinThread 

    程序的运行结果如下:

    n=442

    这个运行结果可能在不同的运行环境下有一些差异,但一般n不会等于1000。从上面的结果可以肯定,这100个线程并未都执行完就将n输出了。

    2.  测试2

    使用如下的命令运行上面的代码:

    在上面的命令行中有一个参数join,其实在命令行中可以使用任何参数,只要有一个参数就可以,这里使用join,只是为了表明要使用join方法使这100个线程同步执行。

    程序的运行结果如下:

    n=1000

    无论在什么样的运行环境下运行上面的命令,都会得到相同的结果:n=1000。这充分说明了这100个线程肯定是都执行完了,因此,n一定会等于1000。


    t.yield(); //暂停当前正在执行的线程对象,并执行其他线程。方法为静态
    //哪个线程体执行此方法,哪个线程让步

     1 public class TestYield {  
     2   public static void main(String[] args) {  
     3     MyThread3 t1 = new MyThread3("t1");  
     4     MyThread3 t2 = new MyThread3("t2");  
     5     t1.start(); t2.start();  
     6   }  
     7 }  
     8 class MyThread3 extends Thread {  
     9   MyThread3(String s){super(s);}  
    10   public void run(){  
    11     for(int i =1;i<=100;i++){  
    12       System.out.println(getName()+": "+i);  
    13       if(i%10==0){  
    14         yield();  
    15       }  
    16     }  
    17   }  
    18 } 

    七、interrupt方法一种让线程退出的方式。

     1 import java.util.*;  
     2 public class TestInterrupt{  
     3     public static void main(String[] args){  
     4         MyThread t = new MyThread();  
     5         t.start();  
     6         try{Thread.sleep(10000);}  
     7         catch(InterruptedException i){}  
     8         t.interrupt();  
     9     }  
    10 }  
    11  
    12 class MyThread extends Thread{  
    13     public void run(){  
    14         while(true){  
    15             try{  
    16                 System.out.println("------"+new Date()+"-----");  
    17                 Thread.sleep(1000);  
    18             }catch(InterruptedException i){  
    19                 return;  
    20             }  
    21         }  
    22     }  
    23 }  
    24  

    八、线程优先级别 
    线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级为5.
    Thread.MAX_PRIORITY=1
    Thread.MIN_PRIORITY=10
    Thread.NORM_PRIORITY=5
    例:t.setPriority(Thread.NORM_PRIORITY+3);
    九、线程同步
    1.同步代码块
    synchronized(this){  //在执行代码块过程中,不会被其他线程打断
    ...  
    }
    public sunchronized void method //执行此方法时,当前对象被锁定
    在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性,每个对象 都对应一个可称为"互斥锁"的标记,这个标记保证在任一时刻,只能有一个线程访 问该对象。
    2.线程死锁

     1 public class TestDeadLock implements Runnable {  
     2     public int flag = 1;  
     3     static Object o1 = new Object(), o2 = new Object();  
     4     public void run() {  
     5 System.out.println("flag=" + flag);  
     6         if(flag == 1) {  
     7             synchronized(o1) {  
     8                 try {  
     9                     Thread.sleep(500);  
    10                 } catch (Exception e) {  
    11                     e.printStackTrace();  
    12                 }  
    13                 synchronized(o2) {  
    14                     System.out.println("1");      
    15                 }  
    16             }  
    17         }  
    18         if(flag == 0) {  
    19             synchronized(o2) {  
    20                 try {  
    21                     Thread.sleep(500);  
    22                 } catch (Exception e) {  
    23                     e.printStackTrace();  
    24                 }  
    25                 synchronized(o1) {  
    26                     System.out.println("0");  
    27                 }  
    28             }  
    29         }  
    30     }      
    31       
    32     public static void main(String[] args) {  
    33         TestDeadLock td1 = new TestDeadLock();  
    34         TestDeadLock td2 = new TestDeadLock();  
    35         td1.flag = 1;  
    36         td2.flag = 0;  
    37         Thread t1 = new Thread(td1);  
    38         Thread t2 = new Thread(td2);  
    39         t1.start();  
    40         t2.start();  
    41           
    42     }  
    43 } 

    十、生产者消费者问题

     1 public class ProducerConsumer {  
     2     public static void main(String[] args) {  
     3         SyncStack ss = new SyncStack();  
     4         Producer p = new Producer(ss);  
     5         Consumer c = new Consumer(ss);  
     6         new Thread(p).start();  
     7         new Thread(p).start();  
     8         new Thread(p).start();  
     9         new Thread(c).start();  
    10     }  
    11 }  
    12  
    13 class WoTou {  
    14     int id;   
    15     WoTou(int id) {  
    16         this.id = id;  
    17     }  
    18     public String toString() {  
    19         return "WoTou : " + id;  
    20     }  
    21 }  
    22  
    23 class SyncStack {        //栈实现  
    24     int index = 0;  
    25     WoTou[] arrWT = new WoTou[6];    //相当于装物品的篮子  
    26       
    27     public synchronized void push(WoTou wt) {    //生产物品,线程安全  
    28         while(index == arrWT.length) {        //当篮子满了线程等待  
    29             try {              
    30                 this.wait();          
    31             } catch (InterruptedException e) {  
    32                 e.printStackTrace();  
    33             }  
    34               
    35         }  
    36         this.notifyAll();    //开始生产时,叫醒等待的其他线程开始消费  
    37         arrWT[index] = wt;      
    38         index ++;  
    39     }  
    40       
    41     public synchronized WoTou pop() {        //消费物品,线程安全  
    42         while(index == 0) {            //如果篮子空了  
    43             try {  
    44                 this.wait();        //线程等待,等待生产者开始                           
    45 //生产,叫醒此线程  
    46             } catch (InterruptedException e) {  
    47                 e.printStackTrace();  
    48             }  
    49               
    50         }  
    51         this.notifyAll();            //消费时喊醒生产者生产  
    52         index--;  
    53         return arrWT[index];  
    54     }  
    55 }  
    56  
    57 class Producer implements Runnable {            //生产者类  
    58     SyncStack ss = null;  
    59     Producer(SyncStack ss) {  
    60         this.ss = ss;  
    61     }  
    62       
    63     public void run() {  
    64         for(int i=0; i<20; i++) {    //生产20个  
    65             WoTou wt = new WoTou(i);  
    66             ss.push(wt);              
    67             System.out.println("生产了:" + wt);  
    68             try {  
    69                 Thread.sleep((int)(Math.random() * 200));  
    70             } catch (InterruptedException e) {  
    71                 e.printStackTrace();  
    72             }              
    73         }  
    74     }  
    75 }  
    76  
    77 class Consumer implements Runnable {  
    78     SyncStack ss = null;  
    79     Consumer(SyncStack ss) {  
    80         this.ss = ss;  
    81     }  
    82       
    83     public void run() {  
    84         for(int i=0; i<20; i++) {        //消费20个  
    85             WoTou wt = ss.pop();  
    86             System.out.println("消费了: " + wt);  
    87             try {  
    88                 Thread.sleep((int)(Math.random() * 1000));  
    89             } catch (InterruptedException e) {  
    90                 e.printStackTrace();  
    91             }              
    92         }  
    93     }  
    94 }  
  • 相关阅读:
    javascript关于面向对象的总结
    实现ICollection
    sqlbishi
    什么叫IOC(编程术语
    ASP.Net绘制柱状图和曲线图示例
    Web.config配置知识
    asp.net的生成曲线图的过程简单实例
    asp.net与.net编程常用函数与方法汇总
    C# 值类型与类的不同
    一步一步学Linq to sql(一):预备知识
  • 原文地址:https://www.cnblogs.com/abc8023/p/4290904.html
Copyright © 2011-2022 走看看