• 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 }
  • 相关阅读:
    从源码剖析Lua数据类型
    【Mysql】主从同步配置
    【Logstash】Logstash收集Nginx访问日志(二十六)
    【Logstash】Logstash快速入门(二十五)
    【Kibana】集群监控(二十四)
    【Beats】Metricbeat 收集Nginx指标数据(二十三)
    【Beats】Metricbeat快速入门(二十二)
    【Beats】Filebeat 与 Kibana仪表板(二十一)
    【Kibana】坐标地图(二十)
    【Beats】Filebeat收集Nginx日志(十九)
  • 原文地址:https://www.cnblogs.com/wuyn/p/9280167.html
Copyright © 2020-2023  润新知