码迷,mamicode.com
首页 > 编程语言 > 详细

java学习笔记之初识多线程

时间:2017-12-23 01:13:38      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:ati   独立   runnable   电影   star   read   功能   概率   内存   

初识多线程

一.进程的认识:

  1.进程的理解:

  进程可以理解成正在执行的任务,就是正在运行的程序,进程又分为两种,一种是前台进程,就是我们很直观看见的,另一种是后台进程,就是操作系统启动就有的(系统级的进程),每个进程运行之后都会占用一定的cpu和内存资源;

  比如说:我们打开window任务管理器就可以看到有很多的进程,里面有用户开启的,也有操作系统启动的进程

技术分享图片

 

  2.进程的调度:

  也就是那么多的进程,cpu是怎样运行的呢?

  采用时间片轮转法

 技术分享图片

 

二.线程认识

  1.线程的理解

    线程是在进程的内部运行的执行体

    (1).一个进程可以创建多个线程

    (2).进程和线程共同来争夺cpu,而且概率是均等的

    (3).线程依赖进程,不能独立存在

    (4).在java中,一个进程至少有一个线程,main方法被称为主线程;

      我们可以在java的main方法中输出一个1/0;

技术分享图片

 

    (5).进程或者线程都有优先级,优先级高的可以得到更多的时间片和cpu的执行权

    (6).抢占式调度:优先级高的进程可以抢占优先级低的cpu执行权

  2.为什么要搞多线程?

   原因:

    (1).让多个程序同时执行

    (2).提高程序的执行效率

三.线程的创建

  1.方式一:继承Thread类

    小demo:

1 //定义一个类,继承Thread类
2 public  class  MyThread  extends  Thread {
3 
4     //重写Thread类的run方法    
5     public void run(){
6         System.out.print("我是一个子线程");  
7     }
8 }

  

1 public class Demo {
2     public static void main(String[] args) {
3         //创建子类对象,然后调用start();方法
4         MyThread mt=new MyThread();
5         mt.start();
6     }
7 }

 

 

  2.方式二:实现Runnable接口

    小demo:

//实现类的定义
public class MyRunnableImpl  implements Runnable {
    //定义一个Runnable实现类,然后重写run方法
    @Override
    public void run() {
        //这里写功能代码
    }
}
 1 public class Demo {
 2     //使用代码
 3     public static void main(String[] args) {
 4         //new 一个Runnable实现类对象
 5         MyRunnableImpl my=new MyRunnableImpl();
 6         //然后将该实现类对象,传入Thread类的构造方法中,并创建Thread类对象
 7         //调用Thread对象start()方法开启线程
 8         new Thread(my).start();
 9     }
10 }

四.线程的安全

   1.线程安全问题产生的原因:

      当多个线程去访问共享资源时候,就会发生线程安全问题

    先看一个案例:多窗口卖电影票的案例

 1 class  Ticket implements Runnable {
 2     //电影票的数量
 3     private static  int ticket=100;
 4     @Override
 5     public void run() {
 6         while(true){
 7             if(ticket>0){
 8                 //模拟网络延时的场景
 9                 try {
10                     Thread.sleep(50);
11                 } catch (InterruptedException e) {
12                     // TODO Auto-generated catch block
13                     e.printStackTrace();
14                 }
15                 //对票数进行出售(减减操作)
16                 System.out.println("正在售出第"+ticket--+"张票");
17             }
18         }
19     }
20 }
21 public class Demo {
22     public static void main(String[] args) {
23         //new 一个实现类对象
24         Ticket  t=new Ticket();
25         //创建3个线程对电影票进行售卖
26         new Thread(t).start();
27         new Thread(t).start();
28         new Thread(t).start();
29         
30     }
31 }

  这时候就出现了问题:

    技术分享图片

    出现这个问题的解释:

      当拥还剩一张电影票的时候,拥有cpu执行权的线程运行到while(true)的时候,顺利通过,然后在运行sleep();这时候这个线程进入堵塞状态,电影票还是1,cpu的执行权被另一个线程拿到,也正好运行到while(true),顺利通过,然后在运行sleep();cpu执行权被第三个线程抢去,同样的运行,到最后醒过来的线程会继续执行下面的代码。就产生了负数票的现象

   2.线程安全问题的解决方案:

     (1).同步代码块

    

 1      
 2      //定义一个对象,当做锁对象
 3      static Object obj = new Object();
 4      /*
 5         同步代码块:
 6         参数:锁对象
 7         1:java任何对象都可以作为锁对象
 8         2:所有的线程都必须共享这个锁对象(该对象只有一份)
 9         synchronized(mutex){
10             //存放需要加锁的代码
11         }
12       */
13     
14     //实现卖票的代码
15     @Override
16     public void run() {
17         
18         while(true){
19             synchronized (obj) {//加锁
20                 if(tickets > 0 ){
21                     //模拟一个网络的延时
22                     try{Thread.sleep(50);}catch(Exception e){}
23                     System.out.println("正在出售第"+ tickets-- + "张票");
24                 }
25             }//解锁
26         }
27     }

 

     (2).同步方法

 1     /*
 2      * 同步方法:对整个方法加锁
 3      * 
 4      * 1:同步方法的锁对象是this,  这里的this必须是同一个
 5      * 2:静态方法的锁对象是:类名.class
 6      */
 7     /*
 8      * 同步代码块和同步方法的区别:
 9      *     1:同步代码块可以对任何一段代码进行加锁
10      *  2:同步方法是对整个方法都进行加锁
11      *  
12      *  
13      *  3:同步代码块的对象可以自己指定
14      *  4:同步方法的锁对象必须是this
15      */
16     public synchronized void method(){
17         if (tickets > 0) {
18             // 模拟一个网络的延时
19             try {
20                 Thread.sleep(50);
21             } catch (Exception e) {
22             }
23             System.out.println("正在出售第" + tickets-- + "张票");
24         }
25     }
26 
27     // 实现卖票的代码
28     @Override
29     public void run() {
30 
31         while (true) {
32             method();
33         }
34     }

 

     (3).同步锁

 1 /*
 2      * 同步锁:
 3      *  Lock接口:
 4      *      ReentrantLock实现类:
 5      *         lock();    加锁
 6      *         unlock();解锁
 7      */
 8     
 9     //1:创建锁对象
10     ReentrantLock rt = new ReentrantLock();
11     
12     
13     // 实现卖票的代码
14     @Override
15     public void run() {
16 
17         while (true) {
18             //2:在适当的地方加锁
19             rt.lock();
20             
21             if (tickets > 0) {
22                 // 模拟一个网络的延时
23                 try {
24                     Thread.sleep(50);
25                 } catch (Exception e) {
26                 }
27                 System.out.println("正在出售第" + tickets-- + "张票");
28             }
29             //3:在适当的地方解锁
30             rt.unlock();
31         }
32     }

 

五.线程的状态

 

 技术分享图片

 

 

 

 

 

 

  

 

java学习笔记之初识多线程

标签:ati   独立   runnable   电影   star   read   功能   概率   内存   

原文地址:http://www.cnblogs.com/xuzhaocai/p/8087964.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!