Java-第二课线程

废话:“老板,手机是水货好,还是行货好喔?”,“当然水货好涩!你看街上哪有水货手机的维修中心嘛!”--糗百

走着:Java中线程有两种实现方式:1、extends Thread 类 2、implements Runable 接口

1、对于Thread类

 1 public class ThreadDemo01 extends Thread {
 2     public void run() {
 3     for (int i = 0; i < 10; i++) {
 4       System.out.print(Thread.currentThread().getName()+":"+i+",");
 5     }
 6     }
 7     public static void main(String[] args) {
 8         ThreadDemo01 t1=new ThreadDemo01();
 9         ThreadDemo01 t2=new ThreadDemo01();
10         t1.setName("a");//给线程设置名称
11         t2.setName("b");
12         t1.setPriority(MAX_PRIORITY);//设置优先级
13         t2.setPriority(NORM_PRIORITY);
14         t1.start();//调用线程
15         t2.start();
16     }
17 }
结果:a:0,b:0,a:1,b:1,a:2,b:2,a:3,b:3,a:4,b:4,a:5,b:5,a:6,a:7,a:8,a:9,b:6,b:7,b:8,b:9,

把希望并行处理的代码都放在run() 中,stat() 用于自动调用run()。实例化一次是一个线程。线程的优先级的范围是(1-10),Java线程的优先级高只是说明该线程先执行的概率大,不代表一点会先执行。

2、对于Runable接口

 1 public class ThreadDemo02 implements Runnable {
 2     public  void run() {
 3              for (int i = 0; i < 10; i++) {
 4                   System.out.print(Thread.currentThread().getName()+":"+i+",");
 5                 }
 6       }
 7     public static void main(String[] args) {
 8         Runnable r1 = new ThreadDemo02();
 9         Thread t1 = new Thread(r1);//创建线程对象
10         Thread t2 = new Thread(r1);
11         t1.setName("a");//给线程设置名称
12         t2.setName("b");
13         t1.start();//启动线程
14         t2.start();
15       }
16 }
结果:a:0,b:0,a:1,b:1,a:2,b:2,a:3,b:3,a:4,b:4,a:5,b:5,a:6,b:6,a:7,b:7,a:8,b:8,a:9,b:9,

实现Runable接口只需要实例化一次,然后可以创建多个线程,更灵活,推荐使用Runable接口。

3、线程的同步synchronized

public class ThreadDemo02 implements Runnable {
/*第一种synchronized*/
//    public  void run() {
//        synchronized(this){
//             for (int i = 0; i < 10; i++) {
//                 System.out.print(Thread.currentThread().getName()+":"+i+",");
//                }
//        }
//      }
/*第二种synchronized*/
    public synchronized void run() {
             for (int i = 0; i < 10; i++) {
                 System.out.print(Thread.currentThread().getName()+":"+i+",");
                }
      }
      public static void main(String[] args) {
        Runnable r1 = new ThreadDemo02();//向下转型
        Thread t1 = new Thread(r1,"a");
        Thread t2 = new Thread(r1,"b");
        t1.start();
        t2.start();
      }
}
两种同步的结果都是:a:0,a:1,a:2,a:3,a:4,a:5,a:6,a:7,a:8,a:9,b:0,b:1,b:2,b:3,b:4,b:5,b:6,b:7,b:8,b:9,

synchronized是同步锁,加上之后,只有在线程运行结束之后才会放锁。synchronized作用于同一个对象的不同进程,不能作用于多个对象。

public class ThreadDemo02 implements Runnable {
    public synchronized void run() {
             for (int i = 0; i < 10; i++) {
                 System.out.print(Thread.currentThread().getName()+":"+i+",");
                }
      }
      public static void main(String[] args) {
        Runnable r1 = new ThreadDemo02();
        Runnable r2 = new ThreadDemo02();//实例化两个对象的时候
        Thread t1 = new Thread(r1,"a");
        Thread t2 = new Thread(r2,"b");//两个对象的不同的线程
        t1.start();
        t2.start();
      }
}
结果:a:0,b:0,a:1,b:1,a:2,b:2,a:3,b:3,a:4,b:4,b:5,b:6,a:5,a:6,a:7,a:8,a:9,b:7,b:8,b:9,

假如是两个不同的对象的不同线程是不能加synchronized同步锁的。没有意义。

public class ThreadDemo03 implements Runnable {
      public void run() {
        /*不同步的循环*/
            for (int k = 0; k < 3; k++) {
              System.out.print(Thread.currentThread().getName()+ ",no:" + k+";");

            }
            /*同步的循环*/
            synchronized (this) {
              for (int k = 0; k < 3; k++) {
                System.out.print(Thread.currentThread().getName()+ ",yes:" + k+";");
              }
            }
          }
          public static void main(String[] args) {
            Runnable r = new ThreadDemo03();
            Thread t1 = new Thread(r, "a"); 
            Thread t2 = new Thread(r, "b");
            t1.start();
            t2.start();
          }
}
结果:a,no:0;b,no:0;b,no:1;b,no:2;a,no:1;b,yes:0;a,no:2;b,yes:1;b,yes:2;a,yes:0;a,yes:1;a,yes:2;

这个能够更只管的看到,当b线程先加上synchronized时只能它完成释放掉,另一个线程才能调用

4、sleep()

public class ThreadDemo04 implements Runnable {
      public void run() {
            for (int k = 0; k < 5; k++) {
                if(k==2){
                    try {
                        Thread.currentThread();
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(Thread.currentThread().getName()+":"+k);
            }
      }
          public static void main(String[] args) {
            Runnable r = new ThreadDemo04();
            Thread t1 = new Thread(r, "a"); 
            Thread t2=new Thread(r,"b");
//            t1.setPriority(Thread.MAX_PRIORITY);
//            t2.setPriority(Thread.MIN_PRIORITY);
            t1.start();
            t2.start();
          }
}
没有优先级结果:a:0a:1b:0b:1b:2b:3b:4a:2a:3a:4
有优先级的结果:a:0a:1b:0b:1b:2a:2a:3a:4b:3b:4

一个线程在sleep的时候,并不会释放这个对象的锁标志。但是当设置了优先级的时候,一个线程在sleep()中时,另一个线程可以执行。

5、jion()

public class ThreadDemo06 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 ThreadDemo06();
        Thread t = new Thread(r);
        t.start();
//        try {
//            t.join();//不加的话,很难是5。加上之后a就是5  ?
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        System.out.println(a);
      }
}
不加jion结果:0
加jion的结果:5

第一个为什么是0呢?因为为线程分配资源需要时间,而main方法执行完t.start()方法后继续往下执行System.out.println(a)。这个时候得到的结果是a还没有被改变的值0。jion()方法能够让一个线程在方法之前完成,jion()会抛出异常所以需要try,catch,所以加上之后输出的是5。

6、yield()

public class ThreadDemo08 implements Runnable {
      public void run() {
          for (int k = 0; k < 10; k++) {
              if (k == 5 && Thread.currentThread().getName().equals("t1")){
                     Thread.yield();
              }
              System.out.print(Thread.currentThread().getName()
                      + ":" + k+";");
              }
          }
          public static void main(String[] args) {
            Runnable r = new ThreadDemo08();
            Thread t1 = new Thread(r, "a");
            Thread t2 = new Thread(r, "b");
//            t1.setPriority(Thread.MAX_PRIORITY);
//            t2.setPriority(Thread.MIN_PRIORITY);
            t1.start();
            t2.start();
          }
}
没有设置优先级的:a:0;a:1;b:0;a:2;b:1;a:3;b:2;a:4;b:3;a:5;b:4;a:6;b:5;a:7;b:6;a:8;b:7;a:9;b:8;b:9;
设置优先级的:b:0;a:0;b:1;a:1;b:2;a:2;b:3;a:3;b:4;a:4;b:5;a:5;b:6;a:6;b:7;a:7;b:8;a:8;b:9;a:9;

api上说的是:暂停当前正在执行的线程对象,并执行其他线程。yield() 方法与sleep() 方法相似,只是它不能由用户指定线程暂停多长时间。按照SUN的说法:sleep方法可以使低优先级的线程得到执行的机会,当然也可以让同优先级和高优先级的线程有执行的机会。而yield()方法只能使同优先级的线程有执行的机会,就是加不加优先级无所谓。不知道有什么作用。

7、wait(), notify()

public class ThreadDemo09 implements Runnable {
      public static int k = 0;
      public synchronized void run() {
        if (k == 0) {
          for (int i = 0; i < 10; i++) {
            k++;
            if (k == 5) {
              try {
                this.wait();//休息
              }
              catch (Exception e) {}
            }
          }
        }
        if (k != 0) {
          System.out.println(Thread.currentThread().getName()+"线程的k=" + k);
          this.notify();//唤醒
        }
      }
      public static void main(String[] args) {
        Runnable r = new ThreadDemo09();
        Thread t1 = new Thread(r, "a");
        Thread t2 = new Thread(r, "b");
        t1.start();
        t2.start();
      }
}
结果:b线程的k=5
a线程的k=10

wait()休息, notify()唤醒。需要在synchronized中使用,调用wait()方法的时候会释放锁标志。唤醒的时候会唤醒休息中的线程。

a线程先执行,因为是synchronized同步锁,所以a线程执行完之前是不是释放锁的。当k=5的时候,a调用了wait()方法自动释放锁,这个时候b线程执行,因为k是静态变量,所以这个时候b线程的k=5直接输出,然后调用了notify()方法,唤醒wait()中的线程,a线程继续执行,当k=10的时候,输出。

结束:实际上,程序中的多个线程并不是同时执行的。除非线程正在真正的多CPU计算机系统上执行,否则线程使用单CPU必须轮流执行。但是,由于这发生的很快,我们常常认为这些线程是同时执行的。线程的每一次执行结果都不相同。

posted @ 2013-03-13 22:58  lleid  阅读(343)  评论(0)    收藏  举报