黑马程序员-【java基础】-多线程
2015-06-27 09:25
681 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一.多线程概述
java语言的优势之一就是线程处理较为简单。一般操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序被称为一个进程。当一个程序运行时,内部可能包含多个顺序执行流,每个顺序执行流就是一个线程。
进程:同一个操作系统中执行的一个子程序,包含了三部分虚拟CPU,代码,数据。
多进程:同一个操作系统中执行的多个并行的子程序,可以提高CPU的使用率。
线程:同一个进程当中并发执行的子程序流。
多线程:同一个进程中并发执行的多个子程序流。
并发:进程时并发运行的,OS将时间划分为很多时间片段,尽可能均匀分配给正在运行的程序,微观上进程走走停停,宏观上都在运行,这种运行的现象称为并发。
二.线程编程的两种方法
1)Thread类
线程类(Thread)包含了一个可以运行的过程(方法):run()方法。
2)创建一个具体线程的步骤如下:
第一,继承Thread类。
第二,覆盖run方法(就是更新运行过程),实现用户自己的过程。
第三,创建线程实例(就是创建一个线程)
第四,使用线程实例的start()方法启动线程,启动后线程会尽快的去并发执行run()
方法一:继承Thread类
实现步骤:
1.继承Thread类,覆盖run()方法,提供并发运行的过程。
2.创建这个类的实例
3.使用start()方法开启线程。
1.main()方法也是一个线程
2.单核,双核,多核处理器的输出结果会不一样
方法二:实现Runnable接口
实现步骤:
1.实现Runnable接口,实现run()方法,提供并发执行的过程
2.创建这个类的实例,用这个实例作为Thread构造器参数,创建Thread类
3.使用start()方法启动线程
三.线程的5种状态
1) New新建状态
当程序使用new关键字创建了一个线程后,该线程就处于新建状态,此时线程还未启动,当线程对象调用start()方法时,线程启动,进入Runnable状态。
2)Runnable可运行状态
当线程处于Runnable状态时,表示线程准备就绪,等待获取CPU
3)Running运行状态
假如线程获取了CPU,则进入Running状态,开始执行线程体,开始执行run方法。
4)Block阻塞状态
当如下情况下,线程会进入阻塞状态:
1.线程调用了sleep()方法主动放弃所占CPU资源。
2.线程调用了一个阻塞式IO方法,在该方法返回前,该线程被阻塞。
当正在执行的线程被阻塞时,其他线程就获得执行权限,
5)Dead死亡状态
1.当线程的run方法执行结束,线程进入Dead状态
2.需要注意的是,不要试图对一个已经死亡的线程进行start()方法,线程死亡后将不能再次作为线程执行,系统会抛出IllegalThreadStateException异常
四.线程的同步
多线程并发访问同一个对象,如果不对线程进行同步控制,破坏了原子操作,则会造成临界资源的数据不一致。
每一个对象都有一个互斥的锁标记和一个锁池,当线程拥有这个对象的锁标记时才能访问这个资源,没有锁标记便进入锁池,保证在同步代码块中只有一个线程,解决了多线程的同步控制问题。
synchronized修饰代码块:对括号内的对象object加锁,只有拿到对象锁标记的线程才能进入该代码块。
注意:
1.静态方法可以是同步方法,但是他所锁的并不是当前对象,是类对象
2.抽象方法不能是synchronized同步的方法
3.构造方法不能是synchronized同步的方法
1.等待唤醒机制:
Wait, notify() notifyAll() 都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。
即等待和唤醒必须是同一个锁。
2.如何停止线程?
开启多线程运行,运行代码通常是循环结构的,只要控制住循环,就可以让run方法结束,从而线程结束。
3.join:当A线程执行到了B线程的.join方法时,A就会等待,等B线程都执行完了,A才执行。Join可以用来临时加入线程执行。
3.并行和并发
并行:是在逻辑上同时发生,指在某一个时间内同时运行多个程序。
并发:物理上同时发生,指在某一个时间点上同时运行多个程序。
4.JVM虚拟机的启动是单线程还是多线程?
多线程,因为垃圾回收也要先启动,否则很容易出现内存溢出。
最简单的也是垃圾回收线程和主线程。
一.多线程概述
java语言的优势之一就是线程处理较为简单。一般操作系统都支持同时运行多个任务,一个任务通常就是一个程序,每个运行中的程序被称为一个进程。当一个程序运行时,内部可能包含多个顺序执行流,每个顺序执行流就是一个线程。
进程:同一个操作系统中执行的一个子程序,包含了三部分虚拟CPU,代码,数据。
多进程:同一个操作系统中执行的多个并行的子程序,可以提高CPU的使用率。
线程:同一个进程当中并发执行的子程序流。
多线程:同一个进程中并发执行的多个子程序流。
并发:进程时并发运行的,OS将时间划分为很多时间片段,尽可能均匀分配给正在运行的程序,微观上进程走走停停,宏观上都在运行,这种运行的现象称为并发。
二.线程编程的两种方法
1)Thread类
线程类(Thread)包含了一个可以运行的过程(方法):run()方法。
2)创建一个具体线程的步骤如下:
第一,继承Thread类。
第二,覆盖run方法(就是更新运行过程),实现用户自己的过程。
第三,创建线程实例(就是创建一个线程)
第四,使用线程实例的start()方法启动线程,启动后线程会尽快的去并发执行run()
方法一:继承Thread类
实现步骤:
1.继承Thread类,覆盖run()方法,提供并发运行的过程。
2.创建这个类的实例
3.使用start()方法开启线程。
class MyThread extends Thread { public void run() { System.out.println("覆盖run()方法"); } } public class test { public static void main(String[] args) { // TODO Auto-generated method stub Thread t1=new MyThread(); //调用start()来启动线程,线程启动方法 t1.start(); } }注:
1.main()方法也是一个线程
2.单核,双核,多核处理器的输出结果会不一样
方法二:实现Runnable接口
实现步骤:
1.实现Runnable接口,实现run()方法,提供并发执行的过程
2.创建这个类的实例,用这个实例作为Thread构造器参数,创建Thread类
3.使用start()方法启动线程
class MyThread2 implements Runnable { public void run() { System.out.println("覆盖run()方法"); } } public class TestThread2{ public static void main(String[] args) { Runnable myThread=new MyThread2(); Thread t1=new Thread(myThread); t1.start(); } }
三.线程的5种状态
1) New新建状态
当程序使用new关键字创建了一个线程后,该线程就处于新建状态,此时线程还未启动,当线程对象调用start()方法时,线程启动,进入Runnable状态。
2)Runnable可运行状态
当线程处于Runnable状态时,表示线程准备就绪,等待获取CPU
3)Running运行状态
假如线程获取了CPU,则进入Running状态,开始执行线程体,开始执行run方法。
4)Block阻塞状态
当如下情况下,线程会进入阻塞状态:
1.线程调用了sleep()方法主动放弃所占CPU资源。
2.线程调用了一个阻塞式IO方法,在该方法返回前,该线程被阻塞。
当正在执行的线程被阻塞时,其他线程就获得执行权限,
5)Dead死亡状态
1.当线程的run方法执行结束,线程进入Dead状态
2.需要注意的是,不要试图对一个已经死亡的线程进行start()方法,线程死亡后将不能再次作为线程执行,系统会抛出IllegalThreadStateException异常
四.线程的同步
多线程并发访问同一个对象,如果不对线程进行同步控制,破坏了原子操作,则会造成临界资源的数据不一致。
每一个对象都有一个互斥的锁标记和一个锁池,当线程拥有这个对象的锁标记时才能访问这个资源,没有锁标记便进入锁池,保证在同步代码块中只有一个线程,解决了多线程的同步控制问题。
synchronized修饰代码块:对括号内的对象object加锁,只有拿到对象锁标记的线程才能进入该代码块。
class Test implements Runnable { private boolean flag; Test(boolean flag) { this.flag=flag; } public void run() { while(true) { if(flag==true) { synchronized(myLock.locka) { System.out.println("if locka"); synchronized(myLock.lockb) { System.out.println("if lockb"); } } } else { synchronized(myLock.lockb) { System.out.println("else locka"); synchronized(myLock.locka) { System.out.println("else lockb"); } } } } } } class myLock { static Object locka=new Object(); static Object lockb=new Object(); } class DeadLockTest { public static void main(String[] args) { Thread d1=new Thread(new Test(true)); Thread d2=new Thread(new Test(false)); d1.start(); d2.start(); } }
注意:
1.静态方法可以是同步方法,但是他所锁的并不是当前对象,是类对象
2.抽象方法不能是synchronized同步的方法
3.构造方法不能是synchronized同步的方法
1.等待唤醒机制:
Wait, notify() notifyAll() 都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。
为什么这些操作线程的方法要定义Object类中呢?
因为这些方法在操作同步中线程时,都必须要标识它们所操作线程只有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。
不可以对不同锁中的线程进行唤醒。
即等待和唤醒必须是同一个锁。
2.如何停止线程?
开启多线程运行,运行代码通常是循环结构的,只要控制住循环,就可以让run方法结束,从而线程结束。
3.join:当A线程执行到了B线程的.join方法时,A就会等待,等B线程都执行完了,A才执行。Join可以用来临时加入线程执行。
3.并行和并发
并行:是在逻辑上同时发生,指在某一个时间内同时运行多个程序。
并发:物理上同时发生,指在某一个时间点上同时运行多个程序。
4.JVM虚拟机的启动是单线程还是多线程?
多线程,因为垃圾回收也要先启动,否则很容易出现内存溢出。
最简单的也是垃圾回收线程和主线程。
相关文章推荐
- 黑马程序员——内部类的理清
- 黑马程序员--构造函数的理解和怎么去使用
- 【BAT(百度,阿里,腾迅)面试题】
- 黑马程序员——Java基础--面向对象(一)
- 如何成为一名真正专业的程序员
- 《程序员的自我修养》系列技术文章整理收藏
- 面试需要的基础知识-替换空格
- 面试需要的基础知识-合并排序数组
- 黑马程序员-IOS学习笔记(六)Category(类别)
- [置顶] 程序员技术练级攻略
- 黑马程序员——Java基础--抽象
- Axis Aligned Rectangles (Google 面试题, 2016网易游戏校招笔试)
- 黑马程序员——Java基础:工具类、for循环、可变参数、其他类
- 黑马程序员--流程控制
- 黑马程序员--枚举类型和结构体
- 高级程序员离职或跳槽可以像公司申请一个月工资
- 黑马程序员--预处理3中指令
- 黑马程序员--指针与数组字符串
- 黑马程序员——Java内存——基本知识
- 黑马程序员--typedef关键字和结构体 枚举类型