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直接调用,相当于在主线程运行一个函数而已。