首页 > 代码库 > java进阶06 线程初探

java进阶06 线程初探

  线程,程序和进程是经常容易混淆的概念。

  程序:就是有序严谨的指令集

  进程:是一个程序及其数据在处理机上顺序执行时所发生的活动

  线程:程序中不同的执行路径,就是程序中多种处理或者方法。

  线程有两种方法实现

  一:继承Thread 覆盖run方法

  

package Thread;

public class Thread1 {
    public static void main(String[] args){
        MyThread1 thread1=new MyThread1();
        thread1.setName("线程1");
        thread1.start();
        
        MyThread1 thread2=new MyThread1();
        thread2.setName("线程2");
        thread2.start();
        
        for(int i=0;i<5;i++)
            System.out.println("主线程正在执行");
    }
    
}
class MyThread1 extends Thread{
    public void run(){
        for(int i=0;i<20;i++)
        {
        System.out.println(Thread.currentThread().getName()+"正在执行"+i);
        }
    }
}

  由于线程是由CPU随机分配的,所以输出结果中 会发现 各线程的执行顺序也是随机的。

  部分输出结果:

  主线程正在执行
  主线程正在执行
  线程2正在执行0
  线程2正在执行1
  线程2正在执行2
  线程2正在执行3
  线程2正在执行4
  线程1正在执行0
  线程2正在执行5
  线程1正在执行1
  线程2正在执行6

  

  2:实现接口Runnable 实现run方法

  

package Thread;

public class Runnable1 {
    //实际开发推荐使用该方法
    public static void main(String[] args){
        MyThread2 rthread=new MyThread2();
        //由于接口中的方法都是抽象的 所以无法直接调用start()
        Thread thread1=new Thread(rthread);
        Thread thread2=new Thread(rthread);
        
        thread1.setName("线程1");
        thread2.setName("线程2");
        
        thread1.start();    
        thread2.start();
        
        for(int i=0;i<20;i++)
            System.out.println("主线程正在执行");
    }
    
}
//通过实现接口Runnable实现
class MyThread2 implements Runnable{
    public void run(){
        for(int i=0;i<20;i++)
        {
        System.out.println(Thread.currentThread().getName()+"正在执行"+i);
        }
    }
}

  部分输出结果:

  主线程正在执行
  主线程正在执行
  线程1正在执行0
  线程2正在执行0
  线程1正在执行1
  线程2正在执行1

  线程的使用就这么简单,不过在实际开发中一般使用第二种方法好点.

  从程序可以看出,由于是随机分配CPU所以无法实现线程的执行的顺序,那有办法吗?

  有,就是设置优先级

  

package Thread;

public class ThreadPrority {
    public static void main(String[] args){
        MyThread3 rthread=new MyThread3();
        
        Thread thread1=new Thread(rthread);
        Thread thread2=new Thread(rthread);
        
        thread1.setName("线程1");
        thread2.setName("线程2");
        
        thread1.setPriority(1);//设置优先级 默认是5
        thread2.setPriority(9);
        
        thread1.start();        
        thread2.start();
    }
}
//通过实现接口Runnable实现
class MyThread3 implements Runnable{
    public void run(){
        for(int i=0;i<30;i++)
        {
        System.out.println(Thread.currentThread().getName()+"正在执行"+i);
        }
        /*设置了优先级 不代表优先级高的就一定会执行 只有更有几率从CPU那分取到。
         * */
    }
}

  输出结果:

  线程1正在执行0
  线程2正在执行0
  线程1正在执行1
  线程2正在执行1
  线程1正在执行2
  线程2正在执行2
  线程1正在执行3
  线程2正在执行3
  线程1正在执行4
  线程2正在执行4
  线程1正在执行5
  线程2正在执行5
  线程1正在执行6
  线程2正在执行6

  这里你一定会有疑问 这不是没变么,主要是这里循环的次数太低 而计算机运算的速度太快,想要看效果 可以把循环次数调高些。

  这些就是线程的基本操作。线程还可以睡眠,在睡眠的时间段CPU不会让调用它的对象参与竞争。

  

package Thread;

public class ThreadSleep {
    public static void main(String[] args){
        MyThread4 rthread=new MyThread4();
        Thread thread=new Thread(rthread);
        thread.setName("线程");
        thread.start();
    }
}
//通过实现接口Runnable实现
class MyThread4 implements Runnable{
    public void run(){
            for(int i=0;i<100;i++)
            {
            System.out.println(Thread.currentThread().getName()+"正在执行"+i);
            try {
                Thread.sleep(1000);//线程睡眠1s
                } catch (Exception e) {
                // TODO: handle exception
                    System.out.println("线程出错");
                }
            /*只得注意的是 这里要处理线程睡眠的异常,而且不能向上一级throws
             *因为throws,是其调用类的父类或者其实现的接口中有该方法,才能向上throws
             *这里实现的Runnable里面的抽象方法中并没有throws方法
             *所以这里如果throws的话 会出错 只能用try...catch来处理
             */
            }
    }
}

  输出结果:

  线程正在执行0
  线程正在执行1
  线程正在执行2
  线程正在执行3
  线程正在执行4

  它会隔1秒输出一句。Tread.Sleep(1000);这里的1000是毫秒 同时这里要处理异常,值得注意的是。这里的异常只能用try...catch。

  而且不能向上一级throws
      因为throws,是其调用类的父类或者其实现的接口中有该方法,才能向上throws
      这里实现的Runnable里面的抽象方法中并没有throws方法
      所以这里如果throws的话 会出错 只能用try...catch来处理

  就像 线程不能直接调用run方法,而要调用start一样,因为接口中的方法是抽象的。

  在Thread里面可以调用run方法,但是它并不会另开线程,而是把run直接调用,相当于在主线程运行一个函数而已。