---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
了解多线程
了解多线程,先了解概念:
什么是进程。
进程:正在执行的应用程序。
那么什么是线程呢?
线程:应用程序的执行单元,执行路径。
什么是单线程?
单线程:顾名思义,一个应用程序在执行的过程中只有一条执行路径。
那么什么是多线程?
多线程:指的是一个应用程序有多条执行路径。
举例:
在生活中,很形象的例子譬如说是学校食堂。有多个窗口,意味着更多的吞吐量和更高的效率,若是只有一个窗口,后果可能是一面是饭菜没有如期卖完
会造成浪费,一面是部分师生还饿着肚子。而开辟多个窗口本质就是线程的一种体现。
多线程的意义:
多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。
线程是在同一时间需要完成多项任务的时候实现的。
多线程的实现
实现多线程有两种方法:
一是继承thread类:
思路 A:自定义类继承Thread类。
B:在自定义类中重写run方法。
C:创建自定义类对象。
D:启动线程。
二是通过实现runnable接口。//使用Thread实现线程 class MyThread extends Thread { private String name; public MyThread(String name ){ this.name=name; } public void run(){ for(int i=0;i<10;i++){ System.out.println("线程"+name+i); } } } public class ThreadDemo01 { public static void main(String args[]){ MyThread A = new MyThread("A"); //实例线程对象 MyThread B = new MyThread("B"); //实例线程对象 A.start(); B.start(); } }
为什么会有这第二种方法呢?因为如果一个类本身就有父类了,我还想实现多线程,通过继承Thread类就实现不了。 所有就有实现Runnable接口的方式。
思路 A:自定义类实现Runnable接口。
B:重写run()方法。
C:创建自定义类对象。
D:创建线程对象,把自定义类对象的作为构造参数传递。
E:启动线程对象。
//使用Runnable实现线程
class MyThread implements Runnable { private String name; public MyThread(String name){ this.name=name; } public void run(){ for(int i=1;i<=10;i++){ System.out.println("线程"+name+i); } } } public class RunnableDemo01 { public static void main(String args[]){ MyThread A = new MyThread("A"); //实例化线程要执行的任务 MyThread B = new MyThread("B"); //实例化线程要执行的任务 Thread Ta = new Thread(A); //实例化线程,并传递其要执行的任务 Thread Tb = new Thread(B); //实例化线程,并传递其要执行的任务 Ta.start(); //启动线程 Tb.start(); } }
补充思路:通过runnable实现多线程,实现Runnable接口的类必须使用Thread类的实例才能创建线程。通过Runnable接口创建线程分为两步: 1. 将实现Runnable接口的类实例化。 2. 建立一个Thread对象,并将第一步实例化后的对象作为参数传入Thread类的构造方法。 3. 最后通过Thread类的start方法建立线程。
注意:线程的随机性和延迟性,这些将会引发一些安全问题。
如何判断是否有一些安全问题呢?
1 是否有共享数据。
2 共享语句是否被多条语句操作。
3 是否有多个线程在执行。
既然有安全问题,那么如何解决呢?
第一种方法
1 同步代码块
synchronized(锁对象){
被同步的代码
}
第二种方法
2 同步方法
在方法上加同步关键字
锁对象是this。
注意:静态同步方法的锁对象是当前类名.class。(当前的字节码文件对象)
用多线程模拟买票的案例
start()和run()方法的区别:public class Tickets implements Runnable { private int tickets = 100; private Object obj = new Object(); @Override public void run() { while(true) { synchronized(obj) { if(tickets>0) { System.out.println(Thread.currentThread().getName()+"正在售出"+(tickets--)+"张票"); } } } } } public class Test { public static void main(String[] args) { Tickets t = new Tickets(); Thread t1 = new Thread(t,"窗口1"); Thread t2 = new Thread(t,"窗口2"); Thread t3 = new Thread(t,"窗口3"); Thread t4 = new Thread(t,"窗口4"); t1.start(); t2.start(); t3.start(); t4.start(); } }
run()仅仅是封装了被线程执行的代码。
start()可以启动线程,并让jvm自动调用run()方法
线程的生命周期:新建-就绪-(阻塞)-运行--死亡,五个阶段。
当用new 创建完一个线程对象后,该线程处于新建状态
当线程对象调用了start()后,该线程处于就绪状态
如果处于就绪状态的线程获得CPU时间片,开始执行run方法的线程执行体,该线程处于运行状态
如果线程调用了sleep()或者调用了一个阻塞式IO方法等,该线程处于阻塞状态
如果线程的run()执行完成或者抛出一个未捕获的异常等原因,该线程处于死亡状态
---------------------- ASP.Net+Android+IOS开发、.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net