zoukankan      html  css  js  c++  java
  • Java多线程的理解和实例

    编写具有多线程程序经常会用到的方法:run(), start(), wait(), notify(), notifyAll(), sleep(), yield(), join()

    还有一个关键字:synchronized

    下面主要来讲讲:

    线程的创建方式就不需要细说,就2种方式 Thread和Runnable

    1.run()和start()

    实例1:

    public class ThreadTest extends Thread {
    public void run() {
    for (int i = 0; i < 10; i++) {
    System.out.print(" " + i);
    }
    }
    
    public static void main(String[] args) {
    new ThreadTest().start();
    new ThreadTest().start();
    }
    }

    这是一个简单的多线程例子

    实例2:

    public class ThreadTest implements Runnable {
    
    public synchronized void run() {
    for (int i = 0; i < 10; i++) {
    System.out.print(" " + i);
    }
    }
    
    public static void main(String[] args) {
    Runnable r1 = new ThreadTest();
    Runnable r2 = new ThreadTest();
    Thread t1 = new Thread(r1);
    Thread t2 = new Thread(r2);
    t1.start();
    t2.start();
    }
    }

    在这个例子中,run被加上了synchronized,这个程序输出的结果是什么呢?t1和t2是2个对象的线程,不同对象的线程是不同的,所以在这个程序中synchronized 并没有起到作用,对于synchronized的定义来说,是针对同一对象的多个线程来说的,在某一时刻只有一个线程能访问此对象的数据

    实例3:

    public class ThreadTest implements Runnable {
    public synchronized void run() {
    for (int i = 0; i < 10; i++) {
    System.out.print(" " + i);
    }
    }
    
    public static void main(String[] args) {
    Runnable r = new ThreadTest();
    Thread t1 = new Thread(r);
    Thread t2 = new Thread(r);
    t1.start();
    
    t2.start();
    }
    }

    实例4:

    public class ThreadTest implements Runnable {
    public void run() {
    synchronized (this) {
    for (int i = 0; i < 10; i++) {
    System.out.print(" " + i);
    }
    }
    }
    
    public static void main(String[] args) {
    Runnable r = new ThreadTest();
    Thread t1 = new Thread(r);
    Thread t2 = new Thread(r);
    t1.start();
    t2.start();
    }
    }


    实例3和4中,synchronized控制了线程对象的数据共享,输出的结果只能是0123456789,3和4其实区别就是synchronized作用范围

    实例5:

    public class ThreadTest implements Runnable {
    public void run() {
    for (int k = 0; k < 5; k++) {
    System.out.println(Thread.currentThread().getName()
    + " : for loop : " + k);
    
    }
    synchronized (this) {
    for (int k = 0; k < 5; k++) {
    System.out.println(Thread.currentThread().getName()
    + " : synchronized for loop : " + k);
    }
    }
    }
    
    public static void main(String[] args) {
    Runnable r = new ThreadTest();
    Thread t1 = new Thread(r, "t1_name");
    Thread t2 = new Thread(r, "t2_name");
    t1.start();
    t2.start();
    }
    }

    输出结果是:

    t1_name : for loop : 0
    t1_name : for loop : 1
    t1_name : for loop : 2
    t2_name : for loop : 0
    t1_name : for loop : 3
    t2_name : for loop : 1
    t1_name : for loop : 4
    t2_name : for loop : 2
    t1_name : synchronized for loop : 0
    t2_name : for loop : 3
    t1_name : synchronized for loop : 1
    t2_name : for loop : 4
    t1_name : synchronized for loop : 2
    t1_name : synchronized for loop : 3
    t1_name : synchronized for loop : 4
    t2_name : synchronized for loop : 0
    t2_name : synchronized for loop : 1
    t2_name : synchronized for loop : 2
    t2_name : synchronized for loop : 3
    t2_name : synchronized for loop : 4

    第一个for循环没有收synchronized保护,所以t1,t2的执行方式是交错的,第二个循环受synchronized保护,所以结果是有规律的

    2.sleep()方法:

    实例6:

    public class ThreadTest implements Runnable {
    public void run() {

    for (int k = 0; k < 5; k++) {
      if (k == 2) {
      try {
        Thread.currentThread().sleep(5000);
      }
      catch (Exception e) {}
      }
        System.out.println(Thread.currentThread().getName()+ " : " + k);
      }
    }

    public static void main(String[] args) {
      Runnable r = new ThreadTest();
      Thread t1 = new Thread(r, "t1_name");
      Thread t2 = new Thread(r, "t2_name");
      t1.setPriority(Thread.MAX_PRIORITY);
      t2.setPriority(Thread.MIN_PRIORITY);
      t1.start();
      t2.start();
    }
    }

    输出结果:

    t1_name : 0
    t1_name : 1
    t2_name : 0
    t2_name : 1
    t1_name : 2
    t1_name : 3
    t1_name : 4
    t2_name : 2
    t2_name : 3
    t2_name : 4

    t1被设置了最高的优先级,t2被设置了最低的优先级,t1不执行完,t2就没有机会执行。但由于t1在执行的中途休息了5秒中,这使得t2就有机会执行了。

    3.join()方法:主要是让调用改方法的thread完成run方法里面的东西后, 在执行join()方法后面的代码

    实例7:

    public class ThreadTest implements Runnable {
    public static int a = 0;
    public void run() {
    for (int k = 0; k < 5; k++) {
    a = a + 1;
    }
    }
    
    public static void main(String[] args) {
    Runnable r = new ThreadTest();
    Thread t = new Thread(r);
    t.start();
    System.out.println(a);
    }
    }

    实例8:

    public class ThreadTest implements Runnable {
    public static int a = 0;
    public void run() {
    for (int k = 0; k < 5; k++) {
    a = a + 1;
    }
    public static void main(String[] args) throws Exception {
    Runnable r = new ThreadTest();
    Thread t = new Thread(r);
    t.start();
    t.join();
    System.out.println(a);
    }
    }

    实例7和8区别就在于加了个join方法,join能保证调用此方法的线程对象完成对应run方法中的内容,所以实例7来说,不确定输出的是什么,而实例8肯定输出的是5

    4.yield()方法:

    yield() 方法与sleep() 方法相似,只是它不能由用户指定线程暂停多长时间。按照SUN的说法:sleep方法可以使低优先级的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会。而yield()方法只能使同优先级的线程有执行的机会。

    实例9:

    public class ThreadTest implements Runnable {
    public void run() {
    8
    for (int k = 0; k < 5; k++) {
    if (k == 5 && Thread.currentThread().getName().equals("t1")) {
    Thread.yield();
    }
    System.out.println(Thread.currentThread().getName()
    + " : " + k);
    }
    }
    
    public static void main(String[] args) {
    Runnable r = new ThreadTest();
    Thread t1 = new Thread(r, "t1");
    Thread t2 = new Thread(r, "t2");
    t1.setPriority(Thread.MAX_PRIORITY);
    t2.setPriority(Thread.MIN_PRIORITY);
    t1.start();
    t2.start();
    }
    }

    输出结果:

    t1 : 0
    t1 : 1
    t1 : 2
    t1 : 3
    t1 : 4

    t2 : 0
    t2 : 1
    t2 : 2
    t2 : 3
    t2 : 4

    从输出结果上看,yield() 方法不会使不同优先级的线程有执行的机会。本例中t1和t2不同的优先级,在t1被yield的时候,t2也是一点机会也没有,只有等到高优先级t1执行完成之后才有执行的机会,而sleep并不是,可以看看实例6

    5.wait(),notify(),notifyAll()

    首先说明:wait(), notify(),notifyAll() 这些方法由java.lang.Object类提供,而上面讲到的方法都是由java.lang.Thread类提供(Thread类实现了Runnable接口)。

    这三个方法用于协调多个线程对共享数据的存取,所以这三个方法只能在synchronized中使用

    实例10:

    public class ThreadTest implements Runnable {
      public static int shareVar = 0;
      public synchronized void run() {
        if (shareVar == 0) {
        for (int i = 0; i < 10; i++) {
          shareVar++;
          if (shareVar == 5) {
            try {
              this.wait();
            }
            catch (Exception e) {}
          }
         }
        }
      if (shareVar != 0) {
        System.out.print(Thread.currentThread().getName());
        System.out.println(" shareVar = " + shareVar);
        this.notify();
      }
    }
    
    public static void main(String[] args) {
      Runnable r = new ThreadTest();
      Thread t1 = new Thread(r, "t1");
      Thread t2 = new Thread(r, "t2");
      t1.start();
      t2.start();
    }
    }

    输出结果:

    t2 shareVar = 5
    t1 shareVar = 10

    过程:t1线程最先执行。由于初始状态下shareVar为0,t1将使shareVar连续加1,当shareVar的值为5时,t1调用wait() 方法,
    t1将处于休息状态,同时释放锁标志。这时t2得到了锁标志开始执行,shareVar的值已经变为5,所以t2直接输出shareVar的值,
    然后再调用notify() 方法唤醒t1。t1接着上次休息前的进度继续执行,把shareVar的值一直加到10,由于此刻shareVar的值不为0,
    所以t1将输出此刻shareVar的值,然后再调用notify() 方法,由于此刻已经没有等待锁标志的线程,所以此调用语句不起任何作用。

  • 相关阅读:
    2009年放假时间安排
    省钱方便网上手机充话费
    为啥不能嵌入html?
    超出套餐流量的GPRS流量费竟然要贵100倍!怎么没有人管呢!这个价格怎么定的呢!
    2008汶川加油!2008中国加油!!
    thinkpad X200 破音特别厉害!郁闷啊!千万不要买水货!
    送走2008,迎接新的2009!
    "上海启明星电子商务有限公司"偷偷扣你的电话钱
    从公司到凯虹
    供应二级新疆细绒棉150吨
  • 原文地址:https://www.cnblogs.com/shilin000/p/4788417.html
Copyright © 2011-2022 走看看