点击此处返回总目录
有关进程、线程的概念回去看操作系统,为了保持结构完整,这里随便写了一点。 一、进程的概念 进程就是正在运行的程序。程序文件存在硬盘上,当运行的时候,进入内存,就变成了一个进程。 二、线程的概念 以前讲的程序中的多个方法都是顺序执行的。从main开始到结尾,一条路走到黑。这种程序称为单线程程序,优点就是没有安全隐患,缺点就是效率堪忧。为了让多个方法同时执行,可以为程序开通多个路径,每一个路径就是一个线程。 就比如说360安全卫士,是一个进程。里面可以同时查病毒,又同时更新软件,这就是多线程。 再比如说迅雷多线程下载,可以开启多个线程同时下载一个文件。 单核CPU一个时刻只能运行一个线程,来回切换。 三、Thread类的使用(创建线程的一种方式) 步骤:首先定义子类,继承Thread,重写父类的run()方法。 然后在main中,通过new Thread子类的对象,创建进程;调用start()方法执行。 run()方法和start()方法的区别: 重写的run()方法,我们不自己调用,而是通过start()方法调用。线程对象调用start()方法开启线程,并让jvm调用run()方法在开启的线程中执行。如果线程对象直接调用run()方法,就当做普通方法一样执行。 例: SubThread.java
package cn.itcast.demo01; public class SubThread extends Thread{ //要继承Thread类。lang包不需要导包。 public void run(){ //注意重写的run()方法,我们自己不调用。而是由start()方法让虚拟机调用。 for(int i = 0;i<3;i++){ System.out.println("thread.."+i); } } } |
Test.java
package cn.itcast.demo01; public class Test { public static void main(String[] args) { SubThread st = new SubThread(); //创建线程。就是创建Thread子类的对象。 st.start(); //启动线程。调用的是start()方法,不是run()方法。注意start()方法做的事:一是启动线 程,二是指挥JVM调用线程中的run()方法。另外,start()方法只能启动一次。 for(int i = 0;i<3;i++){ System.out.println("main..."+i); } } } |
运行结果: main...0 thread..0 thread..1 thread..2 main...1 main...2 四、Thread类常用方法 1. public String getName() //返回该线程的名称。每一个线程都有自己的名字。main线程的名字就叫"main", 其他新建的线程叫"Thread-0","Thread-1",... 【例1】 2. public static Thread currentThread() //返回当前正在执行的线程对象的引用。【例2】【例3】 3. static void sleep(long millis) //指定线程睡上多少毫秒。sleep()方法哪里都能写。【例4】【例5】 例1:每一个线程都有默认的名字Thread-0,Thread-1,... //Thread.java
package cn.itcast.demo01; public class SubThread extends Thread{ public void run(){ //System.out.println(getName()); //可以在类中调用,也可以使用对象调用。 } } |
//Test.java
package cn.itcast.demo01; public class Test { public static void main(String[] args) { SubThread st = new SubThread(); System.out.println(st.getName()); //Thread-0。线程的名字叫Thread-0,不叫st。 SubThread st1 = new SubThread(); System.out.println(st1.getName()); //Thread-1 } } |
例2:如何获取main线程的名字?因为getName()是非静态方法,而main是静态方法,所以main中不能调用getName()方法。再说了,Test类的父类是Object类,不是Thread类,所以也调用不了Thread类的getName()方法。因此不能通过例1的方式在线程中直接调用getname()获得线程的名字。 要想获得住线程的名字,必须先得到主线程的对象,然后通过对象调用getName()方法获得主线程的线程名。
package cn.itcast.demo02; public class Test { public static void main(String[] args) { Thread th = Thread.currentThread(); System.out.println(th.getName()); //main } } |
例3:其他线程既可以直接调用getName()获得线程名,也可以先得到线程,然后调用getName()。 //SubThread.java
package cn.itcast.demo02; public class SubThread extends Thread { public void run(){ Thread th = Thread.currentThread(); System.out.println(th.getName()); //Thread-0 } } |
//Test.java
package cn.itcast.demo02; public class Test { public static void main(String[] args) { SubThread st = new SubThread(); st.start(); } } |
例4:可以在main中睡眠。
package cn.itcast.demo02; public class Test { public static void main(String[] args) throws InterruptedException { System.out.println("aa"); Thread.sleep(1000); System.out.println("bb"); Thread.sleep(2000); System.out.println("cc"); } } |
例5:也可以在线程中睡眠。 //SubThread.java
package cn.itcast.demo02; public class SubThread extends Thread { public void run(){ System.out.println("aa"); try { Thread.sleep(1000); System.out.println("bb"); Thread.sleep(2000); System.out.println("cc"); } catch (InterruptedException e) { e.printStackTrace(); } } } |
//Test.java
package cn.itcast.demo02; public class Test { public static void main(String[] args) throws InterruptedException { SubThread st = new SubThread(); st.start(); } } |
五、创建线程的另一种方式 步骤: 1. 写一个类,实现Runable接口,重写run()方法。 2. 创建Runable接口的实现类的对象。 3. 创建Thread类的对象,在构造方法中传递Runable接口的实现类的对象。 4. 调用Thread类的start()方法。 实现Runable接口的好处(与继承Thread类的方式比较): 1. 实现Runable接口避免了继承Thread类的单继承的局限性。 2. 降低了程序的耦合性。Thread类与Runable接口没有什么联系,也就是将线程与线程任务进行了分离,而继承Thread类的方式是本身就封装了方法,做死了已经。 3. 实现了资源共享。(后面讲) 例: //SubThread.java
package cn.itcast.demo03; public class SubThread implements Runnable{ public void run(){ System.out.println("aaa"); } } |
//Test.java
package cn.itcast.demo03; public class Test { public static void main(String[] args) { SubThread st = new SubThread(); Thread th = new Thread(st); th.start(); } } |
六、通过匿名内部类的格式实现线程程序 之前讲过匿名内部类,将上面两种创建线程的方式改成匿名内部类的格式。
package cn.itcast.demo04; public class Test { public static void main(String[] args) { //第一种实现线程的方式 new Thread(){ public void run(){ System.out.println("aaa"); } }.start(); //第二种实现线程的方式 Runnable r = new Runnable(){ public void run(){ System.out.println("bbb"); } }; Thread t = new Thread(r); t.start(); //第二种实现线程的方式 new Thread( new Runnable(){ public void run(){ System.out.println("ccc"); } }).start(); } } |
七、线程的状态 |