黑马程序员——多线程
来源:互联网 发布:防骗数据库 编辑:程序博客网 时间:2024/06/03 07:58
------- android培训、java培训、期待与您交流! ----------
一、线程
在计算机中,每一个程序的运行,都是通过线程来实现的。我们可以把一个正在执行的程序称为进程,每一个进程的执行都有一个执行顺序。该顺序是一个执行路径,或者叫控制单元。线程就是进程中的一个独立的控制单元,线程在控制着进程的执行。只要进程中有一个线程在执行,进程就不会结束。一个进程中至少有一个线程。
在多个程序运行时,CPU会随机地在多个进程中快速切换,哪个线程抢到了CPU的执行权,哪个线程就运行。运行Java程序时,虚拟机启动会有一个java.exe的进程,该进程中至少有一个线程负责java程序的执行。而且这个线程运行的代码存在于main方法中,称之为主线程。虚拟机启动除了执行主线程外,还有负责垃圾回收机制的线程。这种在在一个进程中有多个线程执行的方式,就是多线程。
多线程的出现能让程序产生同时运行的效果,提高程序的运行效率。例如:在虚拟机启动后,进程中执行主线程时,一般会根据程序代码,在堆内存中产生很多对象,而对象调用完后,就成了垃圾,如果不及时清理,垃圾过多容易造成内存不足,影响程序的运行。所以如果只有主线程运行,程序的效率可能会很低;而如果有一个负责垃圾回收机制的线程运行时,就会对堆内存中的垃圾进行清理,保证了内存的稳定,就保证了程序的运行效率。
二、创建线程
有两种创建线程的方式:继承Thread类和实现Runnable接口。
(1)继承Thread类
Thread类是Java提供的对线程这类事物描述的类,通过继承Thread类,复写其run方法来创建线程。步骤如下:
1.定义一个类继承Thread。
2.覆盖Thread中的run方法。将自定义的代码放在run方法中,让线程运行时,执行这些代码。
3.创建这个类的对象。相当于创建一个线程。然后用该对象调用线程的start方法。该方法的作用是:启动线程,调用run方法。注意如果直接用对象调用run方法,相当于没有启动创建的线程,还是只有主线程在执行。
覆盖run方法的原因:Thread类用于描述线程。该类就定义了一个功能,用于存储线程要执行的代码。该存储功能就是run方法。也就是说,Thread类中的run方法,用于存储线程要运行的代码。
class MyThread extends Thread { //覆盖父类的run方法,存入运行代码 public void run(){ for(int x=0;x<1000;x++) System.out.println(Thread.currentThread().getName()+"在运行"); } } class ThreadDemo { public static void main(String[] args) { //创建线程 MyThread mt1=new MyThread(); MyThread mt2=new MyThread(); //启动线程 mt1.start(); mt2.start(); for(int x=0;x<1000;x++) System.out.println("Hello World!"); } }
(2)实现Runnable接口
实现Runnable接口,覆盖run方法。这种创建线程的方式避免了单继承的局限性,在定义创建线程时,一般都使用这种方式。具体步骤如下:
1.定义一个类实现Runnable的接口。
2.覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
3.通过Thread类创建线程对象,并将Runnable接口的子类对象作为实际参数传递给Thread类的构造方法。这样做是因为自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定对象的run方法,就必须明确该run方法所属对象。
4.调用Thread类中start方法启动线程。start方法会自动调用Runnable接口子类的run方法。
class myRunnable implements Runnable { public void run() { for(int i=0;i<5;i++) { System.out.println(Thread.currentThread().getName()+"....running : "+ i); } } } class RunnableDemo { public static void main(String[] args) { myRunnable t = new myRunnable(); //创建4个线程 Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); //启动线程 t1.start(); t2.start(); t3.start(); t4.start(); } }三、线程的运行状态
被创建:等待启动,调用start启动。如果线程已经启动,处在运行时,再次调用start方法,没有意义,会提示线程状态异常。
运行状态:具有执行资格和执行权。
临时状态(阻塞):有执行资格,但没有执行权。
冻结状态:遇到sleep(time)方法和wait()方法时,失去执行资格和执行权,sleep方法时间到或者调用notify()方法时,获得执行资格,变为临时状态。
消亡状态:stop()方法,或者run方法结束。
四、线程安全
当多条语句在操作多个线程的共享数据时,当一个线程对多条语句只执行了一部分,还没有执行完时,另一个线程可能就会参与进来执行,这样会导致共享数据的错误。线程的安全问题一旦出现对程序的影响很大。所以Java中提供了解决线程安全问题的方法,叫做同步(synchronized),就是对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行,这样就解决了线程的安全问题。同步中分为两种解决方法,一种是同步代码块,另一种是同步函数
(1)同步代码块
格式:synchronized(对象){需要被同步的代码}
(2)同步函数
格式:就是在函数上加上synchronized即可。因为非静态函数需要被对象调用,所以非静态函数中都有一个所属对象引用,即this。
同步例子:class Ticket implements Runnable { private int ticket = 100; public void run() { while(true) show(); } //通过同步函数,实现同步。 public synchronized void show() { if(ticket>0) System.out.println(Thread.currentThread().getName()+"....sale : "+ ticket--); } } class TicketDemo2 { public static void main(String[] args) { Ticket t = new Ticket(); Thread t1 = new Thread(t); Thread t2 = new Thread(t); Thread t3 = new Thread(t); Thread t4 = new Thread(t); t1.start(); t2.start(); t3.start(); t4.start(); } }
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- 黑马程序员—多线程
- jQuery源码学习(版本1.11)-扩展工具函数
- VCS安装
- LinearLayout添加滚动条
- mac os x yosemite mysql
- 机器学习实践 第2章 K-近邻算法概述 笔记(一)
- 黑马程序员——多线程
- freemarker 笔记
- 黑马程序员——集合类
- OC编译C++类库 出错
- java控制linux
- Android 对ScrollView滚动监听,实现美团、大众点评的购买悬浮效果
- Android 带你从源码的角度解析Scroller的滚动实现原理
- 黑马程序员——IO_编码与解码
- Android onTouch、OnLongClick、onClick及ScrollView滑动事件冲突