zoukankan      html  css  js  c++  java
  • java-线程

    线程是一个程序里面不同的执行路径(理解这个就可以了)

    1.线程的基本概念
    可以通过创建Thread的实例来创建新的线程。
    每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。
    通过调用Thread类的start()方法来启动一个线程。

    2.线程的创建和启动
    第一种
    定义线程类实现Runnable接口
    Thread myThread = new Thread(target) //target为Runnable接口类型。
    Runnable中只有一个方法:
    public void run();//用以定义线程运行体。
    使用Runnable接口可以为多个线程提供共享的数据。
    在实现Runnable接口的类的run方法定义中可以使用Thread的静态方法:
    public static Thread currentThread() //获取当前线程的引用。

    第二种
    可以定义一个Thread的子类并重写其run方法:
    class MyThread extends Thread{
    public void run(){...}
    }
    然后生成该类的对象:
    MyThread myThread = new MyThread(...)

    例子1:使用Runnable接口实现

     1 //main主线程和子线程并行执行
     2 public class TestThread1 {
     3     public static void main(String[] args) {
     4         Runnable1 r = new Runnable1();
     5         //r.run();//方法调用
     6         Thread thread = new Thread(r);
     7         thread.start();//启动一个新线程
     8         for(int i=0;i<100;i++){
     9             System.err.println("MainThread-----"+i);
    10         }
    11     }
    12 }
    13 
    14 class Runnable1 implements Runnable {
    15     public void run() {
    16         for(int i=0;i<100;i++){
    17             System.out.println("Runner1:"+i);
    18         }
    19     }
    20 }

     例子2:从Thread类继承

     1 //main主线程和子线程并行执行
     2 public class TestThread1 {
     3     public static void main(String[] args) {
     4         Runnable1 thread = new Runnable1();
     5         thread.start();//启动一个新线程
     6         for(int i=0;i<100;i++){
     7             System.err.println("MainThread-----"+i);
     8         }
     9     }
    10 }
    11 
    12 class Runnable1 extends Thread{
    13     public void run() {
    14         for(int i=0;i<100;i++){
    15             System.out.println("Runner1:"+i);
    16         }
    17     }
    18 }

    3.常用方法

    sleep方法
    可以调用Thread的静态方法:
    public static void sleep(long milis) throws InterruptedExecption使得当前线程休眠(暂时停止执行millis毫秒)。
    由于是静态方法,sleep可以由类名之间调用:
    Thread.sleep(...)

    例子3

     1 public class TestInterrupt {
     2     public static void main(String[] args) {
     3         MyThread thread = new MyThread();
     4         thread.start();
     5         try {
     6             Thread.sleep(10000);//在哪个线程里调用Thread.sleep方法就让哪个线程睡眠
     7         } catch (InterruptedException e) {}
     8         thread.interrupt();//子线程结束(不是让子线程结束的最好的方法,比较粗暴,可能会导致打开的资源来不及关)
     9         //thread.stop();//(已废弃)方式比interrupt更粗暴。
    10     }
    11 }
    12 
    13 class MyThread extends Thread{
    14     @Override
    15     public void run() {//不可以在后面写throws exception,原因是run重写的,重写的方法不能抛出比被重写方法不同的异常
    16         while(true){
    17             System.err.println("===="+new Date()+"====");
    18             try {
    19                 sleep(1000);
    20             } catch (InterruptedException e) {
    21                 return;
    22             }
    23         }
    24     }
    25 }

    例子4:使用一个变量控制子程序结束

     1 public class TestInterrupt {
     2     public static void main(String[] args) {
     3         MyThread thread = new MyThread();
     4         thread.start();
     5         try {
     6             Thread.sleep(10000);
     7         } catch (InterruptedException e) {}
     8         thread.flag = false;
     9     }
    10 }
    11 
    12 class MyThread extends Thread{
    13     boolean flag = true;//定义一个变量来控制
    14     public void run() {
    15         while(flag){
    16             System.err.println("===="+new Date()+"====");
    17             try {
    18                 sleep(1000);
    19             } catch (InterruptedException e) {
    20                 return;
    21             }
    22         }
    23     }
    24 }

    join方法

    合并某个线程

    例子5

     1 public class TestJoin {
     2     public static void main(String[] args) {
     3         MyThread2 t1 = new MyThread2("t1");
     4         t1.start();
     5         try {
     6             t1.join();//合并t1,把t1合并到主线程来,等t1执行完才执行主线程的
     7         } catch (Exception e) {}
     8         for(int i=0;i<10;i++){
     9             System.err.println("main Thread is "+i);
    10         }
    11     }
    12 }
    13 
    14 class MyThread2 extends Thread{
    15     public MyThread2(String s) {
    16         super(s);
    17     }
    18     @Override
    19     public void run() {
    20         for(int i=0;i<10;i++){
    21             System.err.println("i am "+getName());
    22             try {
    23                 sleep(1000);
    24             } catch (Exception e) {
    25                 return;
    26             }
    27         }
    28     }
    29 }

    yield方法(用的不多)

    让出CPU,给其他线程执行的机会

    例子6

     1 public class TestYeild {
     2     public static void main(String[] args) {
     3         MyThread3 thread3 = new MyThread3("t3");
     4         MyThread3 thread1 = new MyThread3("t1");
     5         thread3.start();
     6         thread1.start();
     7     }
     8 }
     9 
    10 class MyThread3 extends Thread{
    11     public MyThread3(String s) {
    12         super(s);
    13     }
    14     @Override
    15     public void run() {
    16         for(int i=0;i<50;i++){
    17             System.err.println(getName()+"-----"+ i);
    18             if (i%10==0) {
    19                 yield();
    20             }
    21         }
    22     }
    23 }

    线程的优先级别

    用数字表示,范围从1到10,默认是5,优先级越高的得到的CPU的执行的时间片就会越多。

    例子6

     1 public class TestPriority {
     2     public static void main(String[] args) {
     3         Thread thread1 = new Thread(new t1());
     4         Thread thread2 = new Thread(new t2());
     5         thread1.setPriority(Thread.NORM_PRIORITY+3);
     6         thread1.start();
     7         thread2.start();
     8     }
     9 }
    10 
    11 class t1 implements Runnable {
    12     public void run() {
    13         for(int i=0;i<10;i++){
    14             System.err.println("t1:"+i);
    15         }
    16     }
    17 }
    18 
    19 class t2 implements Runnable {
    20     public void run() {
    21         for(int i=0;i<10;i++){
    22             System.err.println("--------t2:"+i);
    23         }
    24     }
    25 }

    执行结果

    t1:0
    t1:1
    --------t2:0
    t1:2
    t1:3
    t1:4
    t1:5
    t1:6
    t1:7
    t1:8
    t1:9
    --------t2:1
    --------t2:2
    --------t2:3
    --------t2:4
    --------t2:5
    --------t2:6
    --------t2:7
    --------t2:8
    --------t2:9
    结果

    4.线程同步

    例子7:不使用线程同步会出现以下问题(结果不对)

     1 public class TestSync implements Runnable {
     2     Timer timer = new Timer();
     3     public static void main(String[] args) {
     4         TestSync test = new TestSync();
     5         Thread t1 = new Thread(test);
     6         Thread t2 = new Thread(test);
     7         t1.setName("t1");
     8         t2.setName("t2");
     9         t1.start();
    10         t2.start();
    11     }
    12     public void run() {
    13         timer.add(Thread.currentThread().getName());
    14     }
    15 }
    16 
    17 class Timer{
    18     private static int num =0;
    19     public void add(String name) {
    20         num++;
    21         try {
    22             Thread.sleep(1);
    23         } catch (InterruptedException e) {}
    24             System.err.println(name +"你是第"+num+"个使用timer的线程");
    25         
    26     }
    27 }

    结果

    t2你是第2个使用timer的线程
    t1你是第2个使用timer的线程
    结果

    例子8:

     1 public class TestSync implements Runnable {
     2     Timer timer = new Timer();
     3     public static void main(String[] args) {
     4         TestSync test = new TestSync();
     5         Thread t1 = new Thread(test);
     6         Thread t2 = new Thread(test);
     7         t1.setName("t1");
     8         t2.setName("t2");
     9         t1.start();
    10         t2.start();
    11     }
    12     public void run() {
    13         timer.add(Thread.currentThread().getName());
    14     }
    15 }
    16 
    17 class Timer{
    18     private static int num =0;
    19     public void add(String name) {
    20     //    public synchronized void add(String name) { //也可以写成这样
    21         synchronized (this) {//该方法被执行过程中当前对象被锁定
    22         num++;
    23         try {
    24             Thread.sleep(1);
    25         } catch (InterruptedException e) {}
    26             System.err.println(name +"你是第"+num+"个使用timer的线程");
    27         }
    28     }
    29 }

    结果

    t1你是第1个使用timer的线程
    t2你是第2个使用timer的线程
    结果

    5.多线程会造成的问题

    死锁

    例子9

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

     6.生产者消费者问题

     例子10

     1 /*
     2  * 生产者消费者问题
     3  * 要  点:
     4  *        1. 共享数据的不一致性/临界资源的保护
     5  *        2. Java对象锁的概念
     6  *        3. synchronized关键字/wait()及notify()方法
     7  */
     8 public class ProducerConsumer {
     9     public static void main(String[] args) {
    10         SyncStack stack = new SyncStack();
    11         Runnable p = new Producer(stack);
    12         Runnable c = new Customer(stack);
    13         Thread p1 =new Thread(p);
    14         Thread c1 = new Thread(c);
    15         p1.start();
    16         c1.start();
    17     }
    18 }
    19 
    20 class SyncStack{ //支持多线程同步操作的堆栈的实现
    21     private int index =0;
    22     private char[] data = new char[6];
    23     public synchronized void push(char c) {
    24         if(index == data.length){
    25             try {
    26                 this.wait();
    27             } catch (InterruptedException e) {
    28             }
    29         }
    30         this.notify();
    31         data[index] = c;
    32         index++;
    33     }
    34     public synchronized char pop() {
    35         if(index == 0){
    36             try {
    37                 this.wait();
    38             } catch (InterruptedException e) {
    39             }
    40         }
    41         this.notify();
    42         index--;
    43         return data[index];
    44     }
    45 }
    46 
    47 class Producer implements Runnable{
    48     SyncStack stack;
    49     public Producer(SyncStack s) {
    50         stack =s;
    51     }
    52     
    53     @Override
    54     public void run() {
    55         for(int i=0;i<20;i++){
    56              char c =(char)(Math.random()*26+'A');
    57              stack.push(c);
    58              System.err.println("producer"+c);
    59              try {
    60                 Thread.sleep((int)Math.random()*1000);
    61             } catch (InterruptedException e) {}
    62         }
    63         
    64     }
    65     
    66 }
    67 
    68 class Customer implements Runnable{
    69     SyncStack stack;
    70     public Customer(SyncStack s) {
    71         stack =s;
    72     }
    73     
    74     @Override
    75     public void run() {
    76         for(int i=0;i<20;i++){
    77              char c =stack.pop();
    78              System.out.println("消费:"+c);
    79              try {
    80                 Thread.sleep((int)Math.random()*1000);
    81             } catch (InterruptedException e) {}
    82         }
    83         
    84     }
    85 }
  • 相关阅读:
    request.getParameter() 、 request.getInputStream()和request.getReader() 使用体会
    HTTP之Content-Length
    关于spring3中No Session found for current thread!and Transaction的配置和管理(转)
    Java数据类型和MySql数据类型对应一览
    Spring MVC 解读——View,ViewResolver(转)
    LeetCode 441. Arranging Coins
    LeetCode 415. Add Strings
    LeetCode 400. Nth Digit
    LeetCode 367. Valid Perfect Square
    LeetCode 326. Power of Three
  • 原文地址:https://www.cnblogs.com/wuyn/p/9280167.html
Copyright © 2011-2022 走看看