黑马程序员 java 基础 毕向东 面向对象 多线程
2014-09-14 22:29
615 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
黑马程序员 java 基础 毕向东 面向对象 多线程
* 每一个进程执行都有一个执行顺序,该顺序是一个执行路径
* 或者叫一个控制单元
*
* 线程 才是进程中独立的控制单元
* 线程在控制着进程的执行
* 一个进程中至少有一个线程
*
* java 虚拟机启动时会有一个进程叫做java.ext
* 该进程中至少有一个进程,负责执行
* 这个线程运行的代码存在于main方法中
* 该线程称为主线程
*
* 扩展:更详细是说
* jvm启动不止一个线程,还有垃圾回收机制的线程
黑马程序员 java 基础 毕向东 面向对象 多线程
1线程介绍
* 线程是一个执行中的程序* 每一个进程执行都有一个执行顺序,该顺序是一个执行路径
* 或者叫一个控制单元
*
* 线程 才是进程中独立的控制单元
* 线程在控制着进程的执行
* 一个进程中至少有一个线程
*
* java 虚拟机启动时会有一个进程叫做java.ext
* 该进程中至少有一个进程,负责执行
* 这个线程运行的代码存在于main方法中
* 该线程称为主线程
*
* 扩展:更详细是说
* jvm启动不止一个线程,还有垃圾回收机制的线程
2 线程实现 继承Thread
package ThreadH; /* * 线程是一个执行中的程序 * 每一个进程执行都有一个执行顺序,该顺序是一个执行路径 * 或者叫一个控制单元 * * 线程 才是进程中独立的控制单元 * 线程在控制着进程的执行 * 一个进程中至少有一个线程 * * java 虚拟机启动时会有一个进程叫做java.ext * 该进程中至少有一个进程,负责执行 * 这个线程运行的代码存在于main方法中 * 该线程称为主线程 * * 扩展:更详细是说 * jvm启动不止一个线程,还有垃圾回收机制的线程 * * * 如何自定义线程呢 * 通过对api查阅,java以及封装了线程这类事物的描述即Thread类 * 继承重新run即可 * 步骤: * 1:继承Thread * 2;复写run方法 * 目的:将自定义的代码存储在run方法中,让线程运行 * 3:调用线程的start方法;有俩个作用,1启动线程2调用run方法 * 结果并不相同,而且main和新线程并不是同时执行, * CPU实际上在线程之间快速切换,cpu 执行到谁,谁运行 * 给人看起来是在同时执行的 * 我们可以形象的多线程的运行行为在互相抢夺CPU的执行权 * 执行多长时间,CPU说了算 * * 为什么要覆盖run方法呢 * Thread 类用于描述线程。 * 该类就定义了一个功能,用于存储线程要运行的代码,该 * 存储功能就是run方法 * 也就是说 Thread 的run方法 用于存储线程要执行的代码 * 问题来了: * */ public class ThreadDemo{ public static void main(String args[]) { Demo d=new Demo(); d.start(); //开启线程并执行该线程的run方法 // d.run();仅仅是对象的调用 for(int i=0;i<100;i++) System.out.println("main run"); } } class Demo extends Thread{ public void run(){ for(int i=0;i<100;i++) System.out.println("demo run"); } }
3 线程名字
package ThreadH; /* * 线程都有自己默认的名字 *THread-编号 从零开始 *static Thread currenThread()获取当前线程的对象 *getName() 获取线程的名称 *setName() 或者使用构造函数 设置名称*/ public class ThreadTestT{ public static void main(String[] args) { TestT t=new TestT("t1"); TestT t2=new TestT("t2"); t.start(); t2.start(); for (int i = 0; i < 60; i++) { System.out.println("main run +"+i); } } } class TestT extends Thread{ // private String name; public TestT(String name) { super(name); // this.name=name; } public void run() { for (int i = 0; i < 60; i++) { // System.out.println(name+"test run +"+i); System.out.println((Thread.currentThread()==this)+this.getName()+"test run +"+i); } } }
4 卖票程序 中 体现Runnable 实现方式 and 实现线程同步 and 线程同步锁 this
package ThreadH; /*需求:简单的卖票程序 * 多个窗口卖票 * 创建线程的第二中方式: * 1;定义类实现Runnable接口, * 2:覆盖Runnable接口中的run方法 * 将线程要运行的代码存放在run方法中 * * 3:通过Thread类建立线程对象 * 4:将Runnable接口的子类对象作为实际参数传递给Thread类的构造函 * why?因为自定义的 的run方法所属的对象是Runnable接口的子类对象 * 所以要让线程去指定对象的run方法,就必须明确该run方法所属对象 * 5:调用Thread类的start方格,开启线程并执行Runnable中的run方法 * * 实现方式和继承方式的区别; *关键的部分: *避免了单继承的局限性 *建议使用 的多线程实现方式 * *区别: *继承Thread线程代码存放在Thread的子类run方法中 * *实现Runnable 线程代码存放在接口子类的run方法 * * *通过分析,发现打印出0 -1 -2 等错票 *多线程的运行出现了安全问题 * *问题产生的原因: *当多条语句在操作线程共享数据时,一个线程对多条语句只执行了一部分,还木有执行完, *另一个线程进入参与执行,导致共享数据 的错误 * *解决办法: *对多条操作共享数据 的语句,只能让一个线程执行完,在执行过程中, *其他线程不可以参与执行 * *java 对于多线程的安全问题提供了专业的解决方式 *就是同步代码块 *synchronized(对象){ * 需要被同步的代码 *} * *对象如同锁,持有锁的线程可以在同步中执行 *没有持有锁 的线程即使获取CPU 的执行权,也进不去,因为没获取锁 *火车上的卫生间------------经典同步 * *使用同步的前提: *1:必须有两个或两个以上的线程 *2:必须是多个线程使用同一个锁 *必须保证同步中只有一个线程在运行 * *好处:解决了多线程的安全问题 *弊端:多个线程每一次都需要判断,消耗了资源, * * **同步函数用的是哪个锁呢??? * --------this----- * 函数需要被对象调用,函数都有所属对象的引用 * 所以同步函数使用的锁是this * * 使用该程序进行验证: * 一个线程在同步代码块中 * 一个线程在同步函数中 * 都在执行卖票动作 * Thread-1shwo sale:0 出现错票 * */ public class TicketThread { public static void main(String[] args) { // Ticket ticket1=new Ticket(); // Ticket ticket2=new Ticket(); // Ticket ticket3=new Ticket(); // Ticket ticket4=new Ticket(); // ticket1.start(); // ticket2.start(); // ticket3.start(); // ticket4.start(); // ticket1.start(); // ticket1.start(); // ticket1.start(); // ticket1.start(); Ticket ticket=new Ticket(); //构造方法:解决Thread(Runnable runnable) Thread t1=new Thread(ticket); Thread t2=new Thread(ticket); Thread t3=new Thread(ticket); Thread t4=new Thread(ticket); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket.flag=false; t2.start(); // t3.start(); // t4.start(); } } //class Ticket extends Thread{ // private static int tick=100; // public void run() { // while(true){ // if(tick>0){ // System.out.println(currentThread().getName()+"sale:"+tick--); // } // } // } //} class Ticket implements Runnable{ private static int tick=400; Object obj=new Object(); boolean flag=true; public void run() { if(flag){ while(true){ // synchronized(obj){//同步代码块 synchronized(this){//同步代码块 if(tick>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"run sale:"+tick--); } } } }else{ while(true) show(); } } synchronized void show (){ if(tick>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"shwo sale:"+tick--); } } } //class Ticket implements Runnable{ // private static int tick=400; // Object obj=new Object(); // public void run() { // while(true){ // show(); // } // } // synchronized void show (){ // if(tick>0){ // try { // Thread.sleep(10); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName()+"sale:"+tick--); // } // } //}6
5卖票程序中 静态代码块 同步
package ThreadH; /*需求:简单的卖票程序 * 多个窗口卖票 * 创建线程的第二中方式: * 1;定义类实现Runnable接口, * 2:覆盖Runnable接口中的run方法 * 将线程要运行的代码存放在run方法中 * * 3:通过Thread类建立线程对象 * 4:将Runnable接口的子类对象作为实际参数传递给Thread类的构造函 * why?因为自定义的 的run方法所属的对象是Runnable接口的子类对象 * 所以要让线程去指定对象的run方法,就必须明确该run方法所属对象 * 5:调用Thread类的start方格,开启线程并执行Runnable中的run方法 * * 实现方式和继承方式的区别; *关键的部分: *避免了单继承的局限性 *建议使用 的多线程实现方式 * *区别: *继承Thread线程代码存放在Thread的子类run方法中 * *实现Runnable 线程代码存放在接口子类的run方法 * * *通过分析,发现打印出0 -1 -2 等错票 *多线程的运行出现了安全问题 * *问题产生的原因: *当多条语句在操作线程共享数据时,一个线程对多条语句只执行了一部分,还木有执行完, *另一个线程进入参与执行,导致共享数据 的错误 * *解决办法: *对多条操作共享数据 的语句,只能让一个线程执行完,在执行过程中, *其他线程不可以参与执行 * *java 对于多线程的安全问题提供了专业的解决方式 *就是同步代码块 *synchronized(对象){ * 需要被同步的代码 *} * *对象如同锁,持有锁的线程可以在同步中执行 *没有持有锁 的线程即使获取CPU 的执行权,也进不去,因为没获取锁 *火车上的卫生间------------经典同步 * *使用同步的前提: *1:必须有两个或两个以上的线程 *2:必须是多个线程使用同一个锁 *必须保证同步中只有一个线程在运行 * *好处:解决了多线程的安全问题 *弊端:多个线程每一次都需要判断,消耗了资源, * * **同步函数用的是哪个锁呢??? * --------this----- * 函数需要被对象调用,函数都有所属对象的引用 * 所以同步函数使用的锁是this * * 使用该程序进行验证: * 一个线程在同步代码块中 * 一个线程在同步函数中 * 都在执行卖票动作 * Thread-1shwo sale:0 出现错票 * */ public class StaticTicketThread { public static void main(String[] args) { // Ticket ticket1=new Ticket(); // Ticket ticket2=new Ticket(); // Ticket ticket3=new Ticket(); // Ticket ticket4=new Ticket(); // ticket1.start(); // ticket2.start(); // ticket3.start(); // ticket4.start(); // ticket1.start(); // ticket1.start(); // ticket1.start(); // ticket1.start(); TicketSta ticket=new TicketSta(); //构造方法:解决Thread(Runnable runnable) Thread t1=new Thread(ticket); Thread t2=new Thread(ticket); Thread t3=new Thread(ticket); Thread t4=new Thread(ticket); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket.flag=false; t2.start(); // t3.start(); // t4.start(); } } //class Ticket extends Thread{ // private static int tick=100; // public void run() { // while(true){ // if(tick>0){ // System.out.println(currentThread().getName()+"sale:"+tick--); // } // } // } //} class TicketSta implements Runnable{ private static int tick=400; Object obj=new Object(); boolean flag=true; public void run() { if(flag){ while(true){ // synchronized(obj){//同步代码块 // synchronized(this){//同步代码块 synchronized(TicketSta.class){//同步代码块 if(tick>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"run sale:"+tick--); } } } }else{ while(true) show(); } } // static synchronized void show (){ //如果是静态方法,使用的锁不再是this,因为静态方法不可以定义this //类进入内存,生成对应类的字节码对象 //静态进内存,内存中没有本类对象,但一定有该类对应的字节码文件对象 //类名.class 该对象的类型是Class //静态的同步方法,使用的锁是该方法所在类的字节码文件对象,类名.class 在内存中唯一 static synchronized void show (){ if(tick>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"shwo sale:"+tick--); } } } //class Ticket implements Runnable{ // private static int tick=400; // Object obj=new Object(); // public void run() { // while(true){ // show(); // } // } // synchronized void show (){ // if(tick>0){ // try { // Thread.sleep(10); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println(Thread.currentThread().getName()+"sale:"+tick--); // } // } //}
6银行程序 模拟多线程 操作
package ThreadH; import sun.launcher.resources.launcher; /* *银行有一个金库 *有两个储户,分别存300员,每次存100,存3次 *目的:该程序是否有安全问题? *如果有,如何解决 *如何找到问题: *1:明确哪些代码是多线程运行代码 *for (int i = 0; i < 3; i++) { bank.add(100); } *2:明确共享数据 private int sum; private Bank bank=new Bank(); *3:明确多线程运行代码中是操作共享数据的 * sum+=n; System.out.println("sum="+sum); * * *同步的两种表现形式 *1:同步代码块 synchronized(Object o) { 同步代码} *2:同步函数 将 synchronized 作为函数的修饰符 * * *同步函数用的是哪个锁呢??? * --------this----- * 函数需要被对象调用,函数都有所属对象的引用 * 所以同步函数使用的锁是this * */ public class BankDemo { public static void main(String[] args) { Cus cus=new Cus(); Thread thread1=new Thread(cus); Thread thread2=new Thread(cus); thread1.start(); thread2.start(); } } class Bank{ private int sum; // public void add(int n) { // synchronized (this) { // sum+=n; // try { // Thread.sleep(10); // } catch (InterruptedException e) { // e.printStackTrace(); // } // System.out.println("sum="+sum); // } // // } public synchronized void add(int n) { // synchronized (this) { sum+=n; try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("sum="+sum); // } } } class Cus implements Runnable{ private Bank bank=new Bank(); public void run() { for (int i = 0; i < 3; i++) { bank.add(100); } } }
7单例模式中多线程 的使用 饿汉式 懒汉式
package ThreadH; /* * 单例设计模式 * * 1:饿汉式 * 2:懒汉式 * ------------------------------------------------------- * 饿汉式: * class ClassA { * private static final ClassA c=new ClassA(); * private ClassA(){ * } * public static ClassA getInstance(){ * return c; * } * } * * ------------------------------------------------------- * 懒汉式 * class ClassA { * private static ClassA c=null; * private ClassA(){ * } * public static ClassA getInstance(){ * if(c==null){ * c=new ClassA(); * 为空才实例化对象,所以叫做懒懒 * 也教师延迟加载,对象被延迟了 * } * return c; * } * } * * 懒汉式与饿汉式的区别: * * */ public class SingleDemo { public static void main(String[] args) { } } class Single { private static Single c=null; private Single(){ } public static Single getInstance(){ // public static synchronized Single getInstance(){ //虽然可以解决同步问题,但会低效 //用双重判断可以提高效率 /* * 分析执行过程 * Thread 1执行到if(c==null)为真, * 执行synchronized (Single.class) {} * 获取了锁,其他线程可以可以执行到该行之前,但会在此次等待 * Thread 判断if(c==null) 为真,实例化 c * 执行完同步代码块后退出,其他线程进入同步代码块, * 执行if(c==null) 为假,退出 * 当以后的线程在实例化时,第一行的if(c==null)判断不通过 * 就不会再执行同步代码块 * * 在以后的实例化过程中提高了下效率 * * 最好是选择是使用饿汉式 * */ if(c==null){ synchronized (Single.class) { if(c==null){ c=new Single(); } } } return c; } }
8思索死锁
例子1
package ThreadH; /*思索死锁 * 例如筷子 * * 同步中嵌套同步 * */ public class DeadLockTicketThread { public static void main(String[] args) { TicketDead ticket=new TicketDead(); //构造方法:解决Thread(Runnable runnable) Thread t1=new Thread(ticket); Thread t2=new Thread(ticket); t1.start(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } ticket.flag=false; t2.start(); } } class TicketDead implements Runnable{ private static int tick=1000; Object obj=new Object(); boolean flag=true; public void run() { if(flag){ while(true){ synchronized(obj){//同步代码块 show(); } } }else{ while(true) show(); } } synchronized void show (){ synchronized(obj){//同步代码块 if(tick>0){ try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"run sale:"+tick--); } } } } //}
例子2
package ThreadH; public class DeadLockTest{ public static void main(String args[]) { Thread thread1=new Thread(new TestDe(true)); Thread thread2=new Thread(new TestDe(false)); thread1.start(); thread2.start(); } } class TestDe implements Runnable { private boolean flag; public TestDe(boolean flag) { this.flag= flag; } @Override public void run() { if (flag) { while(true){ synchronized (MyLock.locka) { System.out.println("if locka"); synchronized (MyLock.lockb) { System.out.println("else lockb"); } } } }else { while(true){ synchronized (MyLock.lockb) { System.out.println("else lockb"); synchronized (MyLock.locka) { System.out.println("else locka"); } } }//while } } } class MyLock{ static Object locka=new Object(); static Object lockb=new Object(); }
相关文章推荐
- 黑马程序员 java 基础 毕向东 面向对象 多线程 通信 优化 jdk 1.5 之后新特性Lock
- 黑马程序员 java 基础 毕向东 面向对象 String StringBuffer StringBuilder 基本数据类型包装类
- 黑马程序员_毕向东JAVA基础_多线程
- 黑马程序员_毕向东JAVA基础_面向对象(封装&继承&多态)
- 黑马程序员 java 基础 毕向东 面向对象 异常 以及 package 的使用
- 黑马程序员 java 基础 毕向东 面向对象 常用类 System Math Property Calendar Date Runtime
- 黑马程序员 java 基础 毕向东 面向对象 IO流操作
- 黑马程序员 java 基础 毕向东 面向对象 IO操作 File Properties PrintWriter PrintStream 应用
- 黑马程序员 java 基础 毕向东 面向对象 内部类访问规则
- 黑马程序员_java基础加强9_多线程加强
- 黑马程序员_java基础加强7_多线程加强
- 黑马程序员-Java语言基础– 多线程 第12天
- 黑马程序员---Java基础--09天(面向对象之四异常)
- 黑马程序员-Java语言基础 –面向对象 第6天
- 黑马程序员---Java基础--07天(面向对象之三)
- 黑马程序员-Java语言基础–面向对象 第9天
- 黑马程序员____基础____java的面向对象
- 黑马程序员-Java语言基础–面向对象 第5天
- 黑马程序员—4、JAVA基础&面向对象
- 黑马程序员-Java语言基础 –面向对象 第7天