蒋振飞的博客 - Java入门14:多线程   
正在加载蒋振飞的博客...
V3.0
蒋振飞的博客

Java入门14:多线程

发布时间: 2018年10月17日 发布人: 蒋振飞 热度: 368 ℃ 评论数: 0

一、线程实现

1.实现线程一:继承Thread类

    Thread是程序中的执行线程,Java 虚拟机允许应用程序并发地运行多个执行线程。

2.线程一的步骤

    ①定义一个类继承Thread。
    ②重写run方法。
    ③创建子类对象,就是创建线程对象。
    ④调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法。

3.重写Thread的run方法

package day13;
 

public class ThreadDemo2 {
    public static void main(String[] args) {
        // 创建线程实例
        MyThread mt = new MyThread();
        // 修改线程名字
        mt.setName("张三");
       
        // 启动线程
        mt.start();
       
        // 创建线程实例
        MyThread mt2 = new MyThread();
        mt2.setName("老王");
       
        // 启动线程
        mt2.start();
    }
}

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(getName() + ":" + i);
        }
    }
}

4.实现线程二:实现Runnable接口

    Runnable接口用来指定每个线程要执行的任务。包含了一个 run 的无参数抽象方法,需要由接口实现类重写该方法。    

5.线程二的步骤

    ①定义类实现Runnable接口。

    ②覆盖接口中的run方法。。
    ③创建Thread类的对象
    ④将Runnable接口的子类对象作为参数传递给Thread类的构造函数。
    ⑤调用Thread类的start方法开启线程。

6.重写Runnable接口的run方法

package day13;
 
public class MyThread2 implements Runnable {
    int num;
   
    public MyThread2(int num) {
        this.num = num;
    }
   
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            // Thread t = Thread.currentThread();
            // System.out.println(t.getName() + ":" + i);
           
            // 链式编程
            System.out.println(Thread.currentThread().getName() + ":" + i + num);
        }
    }
}

二、多线程安全问题

1.多线程卖票案例

    需求:用三个线程模拟三个售票窗口,共同卖100张火车票,每个线程打印出卖第几张票。

package day13;

public class TicketThread implements Runnable {
    int tickets = 100;// 火车票数量
   
    @Override
    public void run() {
        // 出售火车票
        while(true) {
            // 当火车票小于0张,则停止售票
            if(tickets > 0) {
           
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
               
                System.out.println(Thread.currentThread().getName() + ":" +tickets--);
            }
        }
    }
 
}

2.多线程安全问题解决

    1) 方法一:使用同步代码块解决。

        synchronized:同步(锁),可以修饰代码块和方法,被修饰的代码块和方法一旦被某个线程访问,则直接锁住,其他的线程将无法访问。

 格式:
  synchronized(锁对象){
      // 需要同步的代码
}
package day13;


public class TicketThread implements Runnable {
    int tickets = 100;// 火车票数量
    Object obj = new Object();
   
    @Override
    public void run() {
        // 出售火车票
        while(true) {
            synchronized (obj) {
 
                if(tickets > 0) {
                   
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                   
                    System.out.println(Thread.currentThread().getName() + ":" +tickets--);
                }
            }
           
        }
    }
 
}

    2) 方法二:使用同步方法解决

        ①非静态同步方法的锁对象是this。

        ②静态的同步方法的锁对象是当前类的字节码对象。

 格式:
  修饰符 synchronized 返回值 方法名(){
 
}
package day13;
/*
 * 同步方法:使用关键字synchronized修饰的方法,一旦被一个线程访问,则整个方法全部锁住,其他线程则无法访问
 * 
 */
public class TicketThread implements Runnable {
    static int tickets = 100;// 火车票数量
    Object obj = new Object();
 
    @Override
    public void run() {
        // 出售火车票
        while (true) {
            /*synchronized (obj) {
                method();
            }*/
           
            //method();
            method2();
 
        }
    }
 
    private synchronized void method() {
        if (tickets > 0) {
          
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
 
            System.out.println(Thread.currentThread().getName() + ":" + tickets--);
        }
    }
   
   
    private static synchronized void method2() {
        if (tickets > 0) {
 
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
 
            System.out.println(Thread.currentThread().getName() + ":" + tickets--);
        }
    }
}

打赏 蒋振飞

取消

感谢您的支持,我会继续努力的!

扫码支持
一分也是爱     一块不嫌多

点击 支付宝 或 微信 打赏蒋振飞

打开支付宝扫一扫,即可进行扫码打赏哦

评论列表