A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 695010894 中级黑马   /  2016-3-30 18:16  /  287 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

/*
进程:是一个正在执行中的程序.
        每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫控制单元.
线程:就是一个进程中的一个独立的控制单元,线程控制着进程的执行.

一个进程中至少有一个线程.

Java VM 启动的时候会有一个进程 java.exe
该进程中至少一个线程负责java程序的执行.
而且这个线程运行的代码存在于main方法中.
该线程称之为主线程.

扩展:其实更细节说明jvm,jvm启动不止主线程一个,还有线程运行负责垃圾回收.

多线程
创建新线程的过程:
1,定义类继承;
2,复写Thread中的run方法:将自定义代码存储在run方法中,让线程运行.
3,调用线程start方法:作用是启动线程,调用run方法.
发现运行结果每一次都不同,是因为多个线程都获取cpu执行权,cpu执行到谁,谁就运行,
cpu在做快速的切换,以达到看上去同时运行的效果,我们可以形象的把多线程的运行行为抢夺
cpu执行权,也就是线程的随机性.

为什么要覆盖run方法:
Thread类用于描述线程;
该类定义了一个功能,用于存储线程要运行的代码,该存储功能就是run方法.
也就是Tread类中的run方法,用于存储线程要执行的代码.

注意run和start方法的区别.

*/
/*
创建线程的第二种方法:实现Runable方法;
1,定义类实现Runable接口;
2,覆盖Runnable借口中的run方法,将线程要运行的代码存放在该run方法中.
3,通过Thread类建立线程对象.
4,将Runable接口的子类对象作为实际参数传递给Thread类的构造函数,为什么呢?
        因为自定义run方法所属的对象是Runable接口中的子类对象,
        要让线程去指定指定对象的run方法,就必须明确该run方法所属对象.
5,调用Thread类的start方法并启动线程调用Runnable接口子类run方法.

实现方式和继承方式有什么区别?
实现方式好处在于避免了单继承的局限性;在定义线程时,建议使用实现方式.
继承Thread:线程代码存放在Thread子类run方法中.
实现Runable:线程代码存放在接口子类的run方法中.
*/

/*
需求:简单的卖票程序:多窗口同时卖票
通过分析,发现打印出0,-1,-2等错票;
  1. class Ticket implements Runnable
  2. {
  3.         private int tick =100;
  4.         Object obj = new Object();
  5.         public void run()
  6.         {
  7.                 while(true)
  8.                 {
  9.                         synchronized(obj)
  10.                         {
  11.                                 if(tick>0)
  12.                                 {
  13.                                         try
  14.                                         {
  15.                                         Thread.sleep(10);
  16.                                         }
  17.                                         catch (Exception e)
  18.                                         {
  19.                                         }
  20.                                 System.out.println(Thread.currentThread().getName() +"...sale:"+tick--);
  21.                                 }
  22.                         }
  23.                 }
  24.         }
  25. }
  26. class TicketDemo
  27. {
  28.         public static void main(String[] args)
  29.         {
  30.                 Ticket t = new Ticket();
  31.                 Thread t1 = new Thread(t);
  32.                 Thread t2 = new Thread(t);
  33.                 Thread t3 = new Thread(t);
  34.                 Thread t4 = new Thread(t);
  35.                 t1.start();
  36.                 t2.start();
  37.                 t3.start();
  38.                 t4.start();

  39.         }
  40. }
复制代码



多线程运行出现安全问题,其原因是:
        当多条语句在操作同一线程共享数据时,一个线程对多条语句只执行一部分,还没执行完,
另一个线程就参与进来执行,导致共享数据的错误.
解决方法:
        对多条操作共享数据的语句,只能让一个线程都执行完.在执行那个过程中,
        不允许其他线程参与.
同步代码块:
synchronized(对象)
        {
                需要被同步的代码
        }
对象如同锁.持有缩的线程可以在同步中执行,
没有持有锁的线程即使获取cpu的执行权,也进不去,因为没有获取锁.

同步的前提:
1,必须要有2个或者2个以上的线程;
2,必须是多个线程使用同一个锁.
必须保证同步中只有一个线程正在执行.
利:解决了多线程的安全问题;
弊:多线程需要判断锁,较为消耗资源.

同步函数用的是哪一个锁?
函数需要被对象调用,那么函数都有一个所属对象引用,就是this.

如果同步函数被静态所修饰,那么锁不是this,因为静态方法中不可以定义this;
静态进内存时,内存中没有本类对象,但是有该类对应的字节码对象:类名.class

单例设计模式--懒汉式.
死锁:

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马