黑马程序员-----多进程
2015-08-20 16:10
609 查看
——- android培训、java培训、期待与您交流! ———-
1、 进程、线程、多线程的区别:
1)进程:是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该循序是一个执行路径,或叫控制单元。
2)线程:是进程中的一个独立的控制单元,线程在控制着进程的执行。
3)多线程:一个进程中可以有多个执行路径。
注意:一个进程中至少要有一个线程。
JVM启动时启动了多条线程,至少有两个线程可以分析的出来:
1.执行main函数的线程,该线程的任务代码都定义在main函数中。
2.负责垃圾回收的线程。
2、 创建线程的两种方法:
第一种方法:继承Thread类。
步骤:1)定义类继承Thread类
2)复写Thread类中的run方法
3)直接创建Thread的子类对象创建线程
4)调用线程的start方法(作用:启动线程;调用run方法)
第二种方法:实现Runnable接口。
步骤:1)定义类实现Runnable接口
2)覆盖Runnable接口中的run方法
3)通过Thread类建立线程对象
4)将Runnable接口的子类对象作为实际参数传给Thread类的构造函数
5)调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
完整代码示例演示:
3、 实现方式和继承方式有什么区别?(重点)
1) 实现方式好处在于避免了单继承的局限性,在定义线程时,建议使用实现方式
2) 线程代码存放的位置不一样
继承Thread类:线程代码存放在Thread子类的run方法中。
实现Runnable接口:线程代码存放在接口的子类的run方法中
4、 线程都有自己默认的名称。Thread-编号(该编号从0开始)
Static Thread currentThread():获取当前线程对象
getName():获取线程名称
设置线程名称:setName或者构造函数
5、线程安全问题产生的原因:
1.多个线程在操作共享的数据。
2.操作共享数据的线程代码有多条。
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。
解决方案:
1)同步代码块:(java对于多线程的安全问题提供了专业的解决方式,就是同步代码块)
2) 同步函数:
示例演示:模拟4个线程同时卖100张票
6、 同步的前提:
1) 必须要有两个或两个以上的线程;
2) 必须保证同步中只有一个线程在运行;
好处:解决了多线程的安全问题
弊端:多个线程需要判断锁,较为消耗资源。
7、 同步有两种表现形式:
一种是同步代码块;一种是同步函数
8、 同步函数使用的锁是this,静态的同步函数使用的锁是该方法所在类的字节码文件对象,即:类名.class
示例演示:储户,两个,每个都到银行存钱,每次存100,共存三次。
单例模式中的懒汉式就用到了同步函数
9、 死锁:同步中嵌套同步,就出现死锁现象。
10、线程间的通信:(等待唤醒机制)
1)操作线程的方法有:wait()/notify()/notifyAll();
为什么这些操作线程的方法要定义在Object类中呢?
分析:因为这些方法在操作同步中的线程时,都必须要标识它们所操作线程特有的锁,只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
2) wait()和sleep()有什么区别?
分析:wait():释放资源释放锁,没有执行权。
sleep():释放资源不释放锁,有执行权。
示例演示:生产者—消费者
11、 停止线程
1) 定义循环结束标记。
因为线程运行代码一般都是循环,只要控制了循环即可。
2) 使用interrupt(中断)方法
该方法是结束线程的冻结状态,是线程回到运行状态中来。
总结:如何停止线程?
只有一种,run方法结束。 开启多线程运行,运行代码通常是循环结构。 只要控制住循环,就可以让run方法结束,也就是线程结束。
12、 守护线程
setDaemon()方法是将该线程标记为守护线程或用户线程(后台线程)。当正在运行的线程都是守护线程时,java虚拟机自动退出。
该方法必须在启动线程前调用。
判断是否是后台线程:使用Thread对象的isDaemon()方法;
例如:
13、 join方法:
调用join方法的线程对象强制运行,该线程强制运行期间,其他线程无法运行,必须等到该线程结束后其他线程才可以运行。
14、 线程的优先级:
每个线程都有优先级,优先级的高低只和线程获得执行机会的次数多少有关。
并非线程优先级越高的就一定先执行,哪个线程的先运行取决于CPU的调度;
默认情况下main线程具有普通的优先级,而它创建的线程也具有普通优先级。
15、 线程让步:(yield)
暂停当前正在执行的线程对象,把执行机会让给相同或更高优先级的其他线程,让线程可以你一个我一个的进行交替执行。
——- android培训、java培训、期待与您交流! ———-
1、 进程、线程、多线程的区别:
1)进程:是一个正在执行中的程序,每一个进程执行都有一个执行顺序,该循序是一个执行路径,或叫控制单元。
2)线程:是进程中的一个独立的控制单元,线程在控制着进程的执行。
3)多线程:一个进程中可以有多个执行路径。
注意:一个进程中至少要有一个线程。
JVM启动时启动了多条线程,至少有两个线程可以分析的出来:
1.执行main函数的线程,该线程的任务代码都定义在main函数中。
2.负责垃圾回收的线程。
2、 创建线程的两种方法:
第一种方法:继承Thread类。
步骤:1)定义类继承Thread类
2)复写Thread类中的run方法
3)直接创建Thread的子类对象创建线程
4)调用线程的start方法(作用:启动线程;调用run方法)
class MyThread extends Thread { public void run() { //要在线程中执行的代码 for(int i=0;i<100;i++) System.out.println("MyThread:"+i); } }
第二种方法:实现Runnable接口。
步骤:1)定义类实现Runnable接口
2)覆盖Runnable接口中的run方法
3)通过Thread类建立线程对象
4)将Runnable接口的子类对象作为实际参数传给Thread类的构造函数
5)调用Thread类的start方法开启线程并调用Runnable接口子类的run方法
class MyThread1 implements Runnable { public void run() { //要在线程中执行的代码 for(int i=0;i<100;i++) System.out.println("MyThread:"+i); } }
完整代码示例演示:
package com.shan; /**需求:建立一个多线程 * @param args */ public class Demo37 { public static void main(String[] args) { System.out.println("启动主线程"); //启动第一个线程 Thread t1=new MyThread(); System.out.println("启动第一个线程"); t1.start(); //启动第二个线程 MyThread1 mt=new MyThread1(); Thread t2=new Thread(mt); System.out.println("启动第二个线程"); t2.start(); } } class MyThread extends Thread //创建线程的第一种方式 { public void run() { //要在线程中执行的代码 for(int i=0;i<100;i++) System.out.println("MyThread:"+i); } } class MyThread1 implements Runnable //创建线程的第二种方式 { public void run() { //要在线程中执行的代码 for(int i=0;i<100;i++) System.out.println("MyThread1:"+i); } }
3、 实现方式和继承方式有什么区别?(重点)
1) 实现方式好处在于避免了单继承的局限性,在定义线程时,建议使用实现方式
2) 线程代码存放的位置不一样
继承Thread类:线程代码存放在Thread子类的run方法中。
实现Runnable接口:线程代码存放在接口的子类的run方法中
4、 线程都有自己默认的名称。Thread-编号(该编号从0开始)
Static Thread currentThread():获取当前线程对象
getName():获取线程名称
设置线程名称:setName或者构造函数
5、线程安全问题产生的原因:
1.多个线程在操作共享的数据。
2.操作共享数据的线程代码有多条。
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。
解决方案:
1)同步代码块:(java对于多线程的安全问题提供了专业的解决方式,就是同步代码块)
格式:synchronized(对象) {需要被同步的代码;}
2) 同步函数:
格式:在函数上加上synchronized修饰符即可。
示例演示:模拟4个线程同时卖100张票
package com.shan; /** * 需求:模拟4个线程同时卖100张票。 * @author ling * */ public class Demo38 { 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(); } } class Ticket implements Runnable { private int num =1000; Object obj=new Object(); public void run() { while(true) { synchronized(obj) { if(num>0) { System.out.println(Thread.currentThread().getName()+"...sale..."+num--); } } } } }
6、 同步的前提:
1) 必须要有两个或两个以上的线程;
2) 必须保证同步中只有一个线程在运行;
好处:解决了多线程的安全问题
弊端:多个线程需要判断锁,较为消耗资源。
7、 同步有两种表现形式:
一种是同步代码块;一种是同步函数
8、 同步函数使用的锁是this,静态的同步函数使用的锁是该方法所在类的字节码文件对象,即:类名.class
示例演示:储户,两个,每个都到银行存钱,每次存100,共存三次。
classBank{ privateintsum; publicsynchronizedvoidadd(intnum){//同步函数 sum=sum+num; System.out.println("sum="+sum); } } classCusimplementsRunnable{ privateBankb=newBank(); publicvoidrun(){ for(intx=0;x<3;x++){ b.add(100); } } } classBankDemo{ publicstaticvoidmain(String[]args){ Cusc=newCus(); Threadt1=newThread(c); Threadt2=newThread(c); t1.start(); t2.start(); } }
单例模式中的懒汉式就用到了同步函数
class Single{ private static Single s = null; private Single(){} public static Single getInstance(){ if(s ==null){ synchronized(Single.class){ if(s == null) s = new Single(); } } return s ; } }
9、 死锁:同步中嵌套同步,就出现死锁现象。
10、线程间的通信:(等待唤醒机制)
1)操作线程的方法有:wait()/notify()/notifyAll();
为什么这些操作线程的方法要定义在Object类中呢?
分析:因为这些方法在操作同步中的线程时,都必须要标识它们所操作线程特有的锁,只有同一个锁上的被等待线程可以被同一个锁上的notify唤醒,不可以对不同锁中的线程唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
2) wait()和sleep()有什么区别?
分析:wait():释放资源释放锁,没有执行权。
sleep():释放资源不释放锁,有执行权。
示例演示:生产者—消费者
class Resource{ private String name ; private String sex ; private boolean flag = false; public synchronized void set(String name,String sex){ if(flag ) try{ this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } this.name = name; this.sex = sex; flag = true ; this.notify(); } public synchronized void out(){ if(!flag ) try{ this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } System. out.println(name + "..." + sex); flag = false ; this.notify(); } } class Input implements Runnable{ Resource r; Input(Resource r){ this.r = r; } public void run(){ int x = 0; while(true ){ if(x == 0){ r.set( "mike","男" ); } else{ r.set( "lili","女" ); } x = (x + 1)%2; } } } //输出 class Output implements Runnable{ Resource r; Output(Resource r){ this.r = r; } public void run(){ while(true ){ r.out(); } } } class ResourceDemo { public static void main(String[] args){ //创建资源 Resource r = new Resource(); //创建任务 Input in = new Input(r); Output out = new Output(r); //创建线程,执行路径 Thread t1 = new Thread(in); Thread t2 = new Thread(out); //开启线程 t1.start(); t2.start(); } }
11、 停止线程
1) 定义循环结束标记。
因为线程运行代码一般都是循环,只要控制了循环即可。
2) 使用interrupt(中断)方法
该方法是结束线程的冻结状态,是线程回到运行状态中来。
总结:如何停止线程?
只有一种,run方法结束。 开启多线程运行,运行代码通常是循环结构。 只要控制住循环,就可以让run方法结束,也就是线程结束。
12、 守护线程
setDaemon()方法是将该线程标记为守护线程或用户线程(后台线程)。当正在运行的线程都是守护线程时,java虚拟机自动退出。
该方法必须在启动线程前调用。
判断是否是后台线程:使用Thread对象的isDaemon()方法;
例如:
StopThread st=new StopThread (); Thread t1=new Thread (st); Thread t2=new Thread (st); t1.setDaemon(true); //如果为true,则表示将该线程标记为守护线程 t2.setDaemon(true); t1.start(); t2.start();
13、 join方法:
调用join方法的线程对象强制运行,该线程强制运行期间,其他线程无法运行,必须等到该线程结束后其他线程才可以运行。
join方法的重载方法: join(long millis): join(long millis,int nanos):
14、 线程的优先级:
每个线程都有优先级,优先级的高低只和线程获得执行机会的次数多少有关。
并非线程优先级越高的就一定先执行,哪个线程的先运行取决于CPU的调度;
默认情况下main线程具有普通的优先级,而它创建的线程也具有普通优先级。
Thread对象的setPriority(int x)和getPriority()来设置和获得优先级。 MAX_PRIORITY : 值是10 MIN_PRIORITY : 值是1 NORM_PRIORITY : 值是5(主方法默认优先级)
15、 线程让步:(yield)
暂停当前正在执行的线程对象,把执行机会让给相同或更高优先级的其他线程,让线程可以你一个我一个的进行交替执行。
——- android培训、java培训、期待与您交流! ———-
相关文章推荐
- 数据库基础(面试常见题)
- Java常见面试题
- 笔试面试题分享
- 看到一个程序员成长之路 一点点感慨
- 黑马程序员——OC视频学习过程6
- 卡特兰数 Catalan数 ( ACM 数论 组合 )
- 程序员的分级理解
- 面试问题
- java面试题笔记2015-08-20
- 黑马程序员-JAVA基础测试题(6-10)
- 魅族面试题小试
- 2014——我的求职(三)
- Android Framework 学习计划 & 职业发展规划 (20150820)
- 黑马程序员---学习笔记24:Foundation框架
- 黑马程序员---学习笔记23:OC基础(10)内存管理
- 黑马程序员---学习笔记22:OC基础(9)
- 黑马程序员---学习笔记21:OC基础(8)
- 黑马程序员---学习笔记19:OC基础(6)
- 黑马程序员---学习笔记20:OC基础(7)
- 黑马程序员---学习笔记18:OC基础(5)