黑马程序员_Java多线程学习
来源:互联网 发布:java 数组最大长度 编辑:程序博客网 时间:2024/05/22 00:37
------- android培训、java培训、期待与您交流! ----------
一个正在运行完整的Java应用程序实例就是一个进程,在这个应用程序中会保护许多小的执行单元,那么每一个执行单元或控制单元就是一个线程。一个应用程序必须至少有一个线程(主线程)。
一、线程的创建
Java中线程的创建方式有两种:1、继承Thread类实现run方法。通过例子说明创建及启动线程的步骤:
class MyThread extends Thread //1、继承Thread类{public MyThread(){}public void run()//2、实现run方法{DoWork();//将要执行的功能}public void DoWork(){}}class MyThreadDemo{public static void main(String[] args){MyThread thread=new MyThread();//3、创建线程子类的对象thread.start();//4、利用start()函数启动线程,并调用run方法}}
注意:该创建方式的一个弊端:因为要创建某线程必须要继承Thread类,而很多情况下一个功能类很可能会继承其他类,Java只支持单继承,那么这个时候就无法再继承Thread类。为了解决这一问题,Java中提供了另外一种创建线程方式,通过实现接口来扩展功能。
2、由于第一中创建线程方式的局限性,第二种方式应运而生——通过实现Runnable接口复写run方法来实现线程的创建。其具体步骤:
class MyFun implements Runnable //1、实现Runnable接口,扩展功能{public MyFun(){}public void run()//2、实现run方法{DoWork();//将要执行的功能}public void DoWork(){}}class MyThreadDemo{public static void main(String[] args){MyFun fun=new MyFun();//3、创建MyFun类的对象(注意它不是线程对象)Thread thread=new Thread(fun);//创建线程对象,并将fun引用作为参数传递给线程的构造函数,与线程建立联系thread.start();//4、利用start()函数启动线程,并调用run方法}}
第二种方式只是对该类进行额外的功能扩展,java就提供了一个接口Runnable并定义了run方法,其实run方法的定义就是为了存储多线程要运行的代码。由于实现Runnable接口可以避免单继承的局限性,所以,通常创建线程都用第二种方式。
二、线程的几种状态。
线程主要有:被创建、运行、冻结(睡眠和等待)、消亡及阻塞等五种状态。
1、线程被创建后通过调用start方法使该线程具有资源的访问资格,同时具备执行权后线程进入运行状态。
2、如果start后该线程拥有了执行资格但是还不具备访问资源的执行权,此时该线程处于临时阻塞状态,当其他线程交出执行权且自己获得执行权后才进入运行状态。
3、对于运行中的线程,可以通过sleep和wait方式将线程进行冻结,对于sleep方式当睡眠时间到,线程自动进入运行状态。而wait方式只能等待别的线程调用notify或notifyAll才能唤醒进入运行状态。各状态之间转换的过程如下图所示:
三、多线程的问题,通常为满足一定的需求,会需要多个线程对同一个资源进行处理,比如一个数据库的写入操作、运算、读取操作等,可能会需要两个以上的线程对这样一个数据库进行处理,那么在线程运行期间会出现数据访问或写入错乱的问题,这就是多线程的安全问题。故未来解决线程安全问题,Java就提供了线程同步机制。
class MulThreaDemo extends Thread{private int count=0;public MulThreaDemo(){}public void run(){for(int i=0;i<10;i++){count += 10;System.out.println(Thread.currentThread().getName()+"----"+this.count);Thread.sleep(20);}} }class Test{MulThreaDemo m1=new MulThreaDemo();MulThreaDemo m2=new MulThreaDemo();MulThreaDemo m3=new MulThreaDemo();m1.start();m2.start();m3.start();}
运行程序我们将会看到m1、m2、m3线程的打印结果是错乱排列的,我本意是要先打印m1结果,然后是m2、m3,这就是由于多个线程同事共享同一个资源造成的,那么,为了解决这个现象,可以利用关键字synchronized来标记同步代码块或同步函数。这个关键字就告诉jvm当前线程拥有访问权,在该线程结束前其他线程不能访问该段代码或函数,此刻其他线程处于等待状态位于线程池中,当线程1执行完后,放弃执行权,那么线程池中等待的线程顺序获得执行权,执行代码。
synchronized的使用方式有两种:同步代码块和同步函数。修饰一个代码块时,synchronized需要指定同步对象,而且保证多线程的同步对象为同一个对象。特殊情况:对于在静态方法内声明同步代码块的地方,在指定同步对象的时候要注意,因为静态方法是在加载类的时候就存在,先于对象引用存在,此时不能再指定所属对象为同步对象,而是要指定为该类的字节码文件对象。
第二种就是同步函数,直接在返回值前添加关键字synchronized(不能放置于返回值的后面)即可。注意同步函数使用的锁对象是this,而同步代码块可以使用任意对象为锁对象。特殊情况是静态方法为同步函数的情况,锁对象不再是this而是该类的字节码文件对象。
eg:
class SynTest{public SynTest(){}//普通方法中指定同步代码块public void method1(){synchronized(this){//要同步的代码}}//注意是静态方法中同步代码块public static void method2(){synchronized(SynTest.class){//需要同步的代码块}}//普通同步函数public synchronized void method3(){}//静态的同步函数public static synchronized void method4(){}}
注意:判断线程同步的两个条件:1、必须有两个或两个以上的线程运行。2、多线程必须保证使用的是同一个同步锁(同步对象)。
- 黑马程序员_java多线程学习
- 黑马程序员_Java多线程学习
- 黑马程序员_java多线程学习笔记
- 黑马程序员_java多线程学习总结
- 黑马程序员_java多线程学习笔记
- 黑马程序员_java学习笔记 6.多线程
- 黑马程序员_java多线程
- 黑马程序员_JAVA多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_Java 多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 黑马程序员_java多线程
- 经济基础和上层建筑
- HDOJ题目1863畅通工程(最小生成树)
- Google发现好领导要有这项“无聊”的特质
- win7系统下使用secureCRT建立与VMware上fedora17的通信
- 正则表达式总结
- 黑马程序员_Java多线程学习
- 编程反省
- 用户更新的sql语句
- 基于Document机制的Swing IP地址控件
- 黑马视频学习笔记-while循环
- 时间格式化。
- opengl es 对bmp 文件贴图程序。
- Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar
- 【算法】 二叉树遍历