多线程技术
第一部分
1、进程和线程
1.1、进程:是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元;1.2、线程:就是进程中的一个独立的控制单元,线程在控制着进程的执行,一个进程中至少有一个线程;1.3、java的虚拟机启动的时候会有一个进程java.exe,该进程中至少一个线程负责java程序的执行,而且这个线程运行的代码存在于main方法中;该线程成为主线程;其实更细节的说,jvm启动不止一个线程,还有负责垃圾回收机制的线程;
1.4、多线程:一个进程里面有多个线程在执行;2、多线程的意义
2.1、可以让程序中的部分能产生同时运行的效果;2.2、可以提高下载的效率;2.3、示例:一个线程在执行主函数,另一个线程在清理垃圾,这样就提高了效率;3、创建线程
Thread:是程序中的执行线程;用与描述控制单元这类事物的一个对象;创建新线程的两种方式:真正创建线程必须是Thread对象或者是Thread的子类对象;
1、继承Thread类
子类覆写父类中的run方法,将线程运行的代码存放在run方法中,-->定义类继承Thread类;建立子类对象的同时线程也被创建。-->复写Thread类中的run方法,目的是将自定义的代码存储在run方法,让线程运行;通过start方法开启线程;-->调用线程的start方法,该方法有两个作用:启动线程和调用润方法;2、实现Runnable接口
子类覆盖接口中的run方法。
通过Thread类创建线程,并将实现了Runnable接口的子类对象最为参数传递给Thread类的构造函数;
Thread类对象调用start方法开启线程;
4、实现方式和继承方式不同
|--接口的好处是学生在继承了人的同时,还可以实现接口-->对外提供了功能性的扩展;
|--实现方式的好处:避免了单继承的局限性;在线程时建议使用实现方式;
|--继承Thread:线程代码存放在Thread子类run方法中;
|--实现Runnable,线程代码存放在接口的子类的run方法;
5、举例
//有两个线程,一个是对象的线程,一个是主线程 //继承Thread类,覆盖run方法; class Demo extends Thread { public void run() { for(int x=0;x<60;x++) System.out.println("demo run--"+x); } } class ThreadDemo { // 主线程 public static void main(String[] args) { Demo d = new Demo(); // 调用run方法,并开启线程; d.start(); for(int x=0;x<60;x++) System.out.println("Hello World--"+x); } }
6、运行结果
主线程和对象d都在抢夺cpu资源;发现每次运行的结果都是不相同的,因为多个线程都获取cpu的执行权,cpu执行到谁,谁就运行,明确一点,在某一个时刻,只能有一个程序在运行,cpu在做着快速的切换以达到看上去是同时运行的结果,我们可以形象的把多线程的运行行为比喻成在互相抢夺cpu的执行权;
7、覆盖run方法的原因
Thread类用于描述线程,该类就定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法;也就是说Thread类中的run方法,用于存储线程要运行的代码;
d.start();开启线程并运行该线程的run方法;
d.run();仅仅是对象调用方法,而线程创建了,并没有运行;
第二部分
1、线程运行状态
2、获取线程对象和名称
线程有自己的默认的名称,Thread-编号,该编号从0开始;
getName();方法可以获取自定义的线程名称;
static Thread currentThread();返回对当前正在执行的线程对象的引用。
设置线程的名称:setName或者构造函数;
3、代码体现
class Test extends Thread { // private String name; Test(String name) { // this.name = name; super(name);//父类中已经定义好了,那么子类就直接拿过来用就好了 } public void run() { for(int x =0;x<60;x++) System.out.println(Thread.currentThread().getName()+"...run..."+x); } } class ThreadTest { public static void main(String[] args) { // 创建两个线程 Test t1 = new Test("one---"); Test t2 = new Test("two+++"); // 开启线程并运行run方法 t1.start(); t2.start(); for(int x=0;x<60;x++) System.out.println("main----"+x); } } //static Thread currentThread()
3、运行结果
自定义线程的名称
4、多线程举例
需求:简单的卖票程序。要求是要多个窗口进行卖票//实现Runnable class Ticket implements Runnable { private static int tick =100; public void run() { while(true) { if(tick>0) System.out.println(Thread.currentThread().getName()+"sale:"+tick--); } } } class TicketDemo { public static void main(String[] args) { // 创建线程;需要传一个Ticket对象;要指定run方法所属对象; // Thread(Runnable target) Ticket t = new Ticket(); // 分别要开启线程 // 4个线程分别开始卖票 new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); /* Ticket t1 = new Ticket(); Ticket t2 = new Ticket(); Ticket t3 = new Ticket(); Ticket t4 = new Ticket(); t1.start(); t2.start(); t3.start(); t4.start(); */ } }
5、运行结果
由于窗口的局限,部分截图;
第三部分
我的总结
|--多线程是为了同步完成多项任务,不是为了提供运行效率,通过提高资源使用效率来提高系统的效率。|--线程是在同一时间需要完成多项任务的时候实现的;|--Thread类中run()和start()方法的区别:
|--run()方法:在本线程没调用该Runnable对象的run()方法,可以重复多次调用;|--start()方法:启动一个线程,调用该Runnable对象的run()方法,不能多次启动一个线程;|--实现方式,因为避免了单继承的局限性,所以创建线程建议使用实现方式;
|--要知道为什么覆盖run()分原因;