Java 多线程案例_多线程使用(坦克大战2.0)持续更新中...

线程相关概念

· 程序

是为完成特定任务、用某种语言编写的一组指令的集合。简单的说:就是我们写的代码

· 进程

1.是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存空间。当我们使用迅雷,又启动了一个进程,操作系统将为迅雷分配新的内存空间。

2.进程是程序的一次执行过程,或是正在运行的一个程序。是动态过程:有它自身的--产生--存在--消亡的过程。

· 线程

1.线程由进程创建,是进程的一个实体

2.一个进程可以拥有多个线程

单线程 :同一个时刻,只允许执行一个线程

多线程:同一个时刻,允许执行多个线程

线程基本使用案例1

package Threaduse;

public class Thread_01 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.start();
    }
}

class Cat extends Thread {
    int times = 0;
    int i = 0;

    @Override
    public void run() {

        while (true) {
            System.out.println("小猫喵喵叫" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            i++;
            if (i == 10) {
                break;
            }
        }
    }
}

线程应用案例1 - 继承Thread类

ava 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。

多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。

package Threaduse;

public class Thread_01 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.start();
        for (int i = 0; i <20 ; i++) {
            System.out.println("主线程" + Thread.currentThread().getName() + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

class Cat extends Thread {
    int times = 0;
    int i = 0;

    @Override
    public void run() {

        while (true) {
            System.out.println("小猫喵喵叫"  + Thread.currentThread().getName() + i );
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            i++;
            if (i == 80) {
                break;
            }
        }
    }
}

jconsle查看线程状况

main和Thread - 0交替运行

main线程结束 ,Thread - 0继续运行

Thread - 0 线程结束

程序结束

线程应用案例2-实现Runnable接口

package Threaduse;


import com.polymorphic_多态.example.多态的应用.Perosn;
import jdk.nashorn.internal.ir.IfNode;

//通过实现接口Runnable 来开发线程
public class Thread_02 {
    public static void main(String[] args) {
        int i = 0;
        Tiger tiger = new Tiger();
        Thread thread = new Thread(tiger);
        thread.start();

        while (true) {
            System.out.println("小猫喵喵叫" + i++ + " " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (i == 20) {
                break;
            }
        }

    }
}


class Animal {
}

class Tiger extends Animal implements Runnable { //java为单继承,故采用implements Runnable实现多线程运行

    @Override
    public void run() {
        int count = 0;
        while (true) {
            System.out.println("老虎嗷嗷叫 " + count++ + " " + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (count == 100) {
                break;
            }
        }
    }
}


//线程代理类 ,模拟一个极简的Thread类 静态代理模式
class ThreadProxy implements Runnable {
    private Runnable target = null;

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }

    public ThreadProxy(Runnable target) {
        this.target = target;
    }

    public void start() {
        start0(); //这个方法是真正实现多线程的方法
    }

    public void start0() {
        run();
    }

}

线程应用案例3 - 多线程执行

package Threaduse;

public class Thread_03 {
    public static void main(String[] args) {

        Hello_Cat helloCat = new Hello_Cat();
        Hello_Dog helloDog = new Hello_Dog();
        Hello_Bird helloBird = new Hello_Bird();
        new Thread(helloCat).start();
        new Thread(helloDog).start();
        new Thread(helloBird).start();


    }
}


class Hello_Cat implements Runnable {
    int count = 0;

    @Override
    public void run() {

        while (true) {
            System.out.println(Thread.currentThread().getName() + "小猫喵喵叫" + count++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (count == 50) {
                break;
            }
        }
    }
}

class Hello_Dog implements Runnable {
    int count = 0;

    @Override
    public void run() {

        while (true) {
            System.out.println(Thread.currentThread().getName() + "小狗旺旺叫" + count++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (count == 50) {
                break;
            }
        }
    }
}

class Hello_Bird implements Runnable {
    int count = 0;

    @Override
    public void run() {

        while (true) {
            System.out.println(Thread.currentThread().getName() + "小鸟吱吱叫" + count++);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (count == 50) {
                break;
            }
        }
    }
}

继承Thread vs 实现Runnable的区别

1、从java的设计来看,通过继承Thread 和Runnable接口来创建本质没有区别

2、实现Runable接口方式更加适合多个线程共享资源的情况,并且避免了单继承的限制,建议使用Runnable

线程应用案例4 - 多线程售票(待解决超售问题) Synchroized

package Threaduse;

public class SellTicket {

    public static void main(String[] args) {

//        TicketsWindows01 tsw1= new TicketsWindows01();
//        new Thread(tsw1).start();
//        new Thread(tsw1).start();
//        new Thread(tsw1).start();


        TicketsWindows02 tsw2 = new TicketsWindows02();
        TicketsWindows02 tsw3 = new TicketsWindows02();
        TicketsWindows02 tsw4 = new TicketsWindows02();
        tsw2.start();
        tsw3.start();
        tsw4.start();

    }
}



//实现Runnable售票
class TicketsWindows01 implements Runnable {
    private  int i = 100;

    @Override
    public void run() {
        while (true) {
            if (i <= 0) {
                System.out.println("售票结束...");
                break;
            }
            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("窗口" + Thread.currentThread().getName() + "剩余票数" + (--i));

        }
    }
}


class  TicketsWindows02 extends Thread{
    static int ticket = 100;
    @Override
    public void run() {

        while (true){
           if (ticket<=0){
              break;
           }
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println("窗口" + Thread.currentThread().getName() + "剩余票数" + (--ticket));

        }

    }
}

线程应用案例5-通知线程退出(线程终止)

package Threaduse.exit;

public class ThreadExit {
    public static void main(String[] args) {

        T t1 = new T();
        t1.start();

        try {
            Thread.sleep(10*1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        t1.setLoop(false);

    }
}

class T extends Thread{
   private int count = 0;
   private boolean loop =true;
    public void setLoop(boolean loop) {
        this.loop = loop;
    }

    @Override
    public void run() {
     while (loop){
         System.out.println("T运行中" + count ++);
         try {
             Thread.sleep(1000);
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
     }

    }
}

通过 main函数中 t1.setLoop(false);控制线程内循环的条件,结束循环-->结束进程

线程常用方法

package com.method;

public class ThreadMethod01 {
    public static void main(String[] args) {


        T t = new T();
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();
        t.setName("----老韩----   ");
        while (true) {
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                    System.out.println("hi");
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println(t.getPriority());
            t.interrupt();
        }

    }
}


class T extends Thread {


    @Override
    public void run() {

        while (true) {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "老韩正在吃包子中" + i);
            }
            try {
                System.out.println(Thread.currentThread().getName() + "休眠中");
                Thread.sleep(1000 * 20);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() + "线程被中断了");
            }
        }
    }
}

线程的插队

package com.method;

public class ThreadMethod02 {
    public static void main(String[] args) throws InterruptedException {

        T2 t2 = new T2();
        t2.start();
        int count = 0;
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + "打工人在吃包子" + i);
            count ++;
            Thread.sleep(1000);
            if (count == 5) {
                t2.join();//子线程插队
            }
        }


    }
}


class T2 extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName() + "老板在吃包子" + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

线程常用方法练习

package com.method;

public class ThreadMethodExercise {
    public static void main(String[] args) throws InterruptedException {
        T3 t3 = new T3();
        Thread thread = new Thread(t3);

        for (int i = 1; i < 11 ; i++) {
            System.out.println(Thread.currentThread().getName() +   " hi " + i );
            Thread.sleep(1000);
            if (i == 5){
                thread.start();
                thread.join();
            }
        }
    }
}

class T3 implements Runnable{

    @Override
    public void run() {
        for (int i = 1; i <11 ; i++) {
            System.out.println(Thread.currentThread().getName() +   " hello " + i );
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}

用户线程和守护线程

package com.method;

public class ThreadMethod03 {
    public static void main(String[] args) throws InterruptedException {

        T4 t4 = new T4();
        t4.setDaemon(true); //打开守护线程,main进程结束,子进程也结束
        t4.start();
        for (int i = 0; i < 10; i++) {
            System.out.println("HELLO" + i);
            Thread.sleep(1000);
        }

    }
}

class T4 extends Thread{
    @Override
    public void run() {
        for (;;){
            System.out.println("hi");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

线程的生命周期

package com.method;

public class Thread_State {
    public static void main(String[] args) {
        T5 t5 = new T5();
        t5.start();
        System.out.println(t5.getName() + t5.getState());
        while(Thread.currentThread().getName() != t5.getName()){
            System.out.println(t5.getName() + t5.getState());
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println(t5.getName() + t5.getState());

    }
}


class T5 extends Thread {
    int count = 0;

    @Override
    public void run() {
        while (true) {
            count++;
            System.out.println(Thread.currentThread().getName() + " ---HELLO ---" + count);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if (count == 5) {
                break;
            }

        }
    }
}

线程同步机制

 

package com.hspedu.syn;

/**
 * @author 韩顺平
 * @version 1.0
 * 使用多线程,模拟三个窗口同时售票100张
 */
public class SellTicket {
    public static void main(String[] args) {

        //测试
//        SellTicket01 sellTicket01 = new SellTicket01();
//        SellTicket01 sellTicket02 = new SellTicket01();
//        SellTicket01 sellTicket03 = new SellTicket01();
//
//        //这里我们会出现超卖..
//        sellTicket01.start();//启动售票线程
//        sellTicket02.start();//启动售票线程
//        sellTicket03.start();//启动售票线程


//        System.out.println("===使用实现接口方式来售票=====");
//        SellTicket02 sellTicket02 = new SellTicket02();
//
//        new Thread(sellTicket02).start();//第1个线程-窗口
//        new Thread(sellTicket02).start();//第2个线程-窗口
//        new Thread(sellTicket02).start();//第3个线程-窗口

        //测试一把
        SellTicket03 sellTicket03 = new SellTicket03();
        new Thread(sellTicket03).start();//第1个线程-窗口
        new Thread(sellTicket03).start();//第2个线程-窗口
        new Thread(sellTicket03).start();//第3个线程-窗口

    }
}


//实现接口方式, 使用synchronized实现线程同步
class SellTicket03 implements Runnable {
    private int ticketNum = 100;//让多个线程共享 ticketNum
    private boolean loop = true;//控制run方法变量
    Object object = new Object();


    //同步方法(静态的)的锁为当前类本身
    //老韩解读
    //1. public synchronized static void m1() {} 锁是加在 SellTicket03.class
    //2. 如果在静态方法中,实现一个同步代码块.
    /*
        synchronized (SellTicket03.class) {
            System.out.println("m2");
        }
     */
    public synchronized static void m1() {

    }
    public static  void m2() {
        synchronized (SellTicket03.class) {
            System.out.println("m2");
        }
    }

    //老韩说明
    //1. public synchronized void sell() {} 就是一个同步方法
    //2. 这时锁在 this对象
    //3. 也可以在代码块上写 synchronize ,同步代码块, 互斥锁还是在this对象
    public /*synchronized*/ void sell() { //同步方法, 在同一时刻, 只能有一个线程来执行sell方法

        synchronized (/*this*/ object) {
            if (ticketNum <= 0) {
                System.out.println("售票结束...");
                loop = false;
                return;
            }

            //休眠50毫秒, 模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
                    + " 剩余票数=" + (--ticketNum));//1 - 0 - -1  - -2
        }
    }

    @Override
    public void run() {
        while (loop) {
            sell();//sell方法是一共同步方法
        }
    }
}

//使用Thread方式
// new SellTicket01().start()
// new SellTicket01().start();
class SellTicket01 extends Thread {

    private static int ticketNum = 100;//让多个线程共享 ticketNum

//    public void m1() {
//        synchronized (this) {
//            System.out.println("hello");
//        }
//    }

    @Override
    public void run() {


        while (true) {

            if (ticketNum <= 0) {
                System.out.println("售票结束...");
                break;
            }

            //休眠50毫秒, 模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
                    + " 剩余票数=" + (--ticketNum));

        }
    }
}


//实现接口方式
class SellTicket02 implements Runnable {
    private int ticketNum = 100;//让多个线程共享 ticketNum

    @Override
    public void run() {
        while (true) {

            if (ticketNum <= 0) {
                System.out.println("售票结束...");
                break;
            }

            //休眠50毫秒, 模拟
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口 " + Thread.currentThread().getName() + " 售出一张票"
                    + " 剩余票数=" + (--ticketNum));//1 - 0 - -1  - -2

        }
    }
}

互斥锁

 同步具体方法-Synchronized

 非静态方法的锁

 静态方法的锁,锁加在类本身上

这段代码无法锁住,对象不共享,不是同一个对象

线程死锁

package com.hspedu.syn;

public class DeadLock {
    public static void main(String[] args) {

        DeadLockDemo A = new DeadLockDemo(true);
        A.setName("A线程");
        DeadLockDemo B = new DeadLockDemo(false);
        B.setName("B线程");
        A.start();
        B.start();

    }
}


class DeadLockDemo extends Thread {
        boolean flag ;
    static Object o1 = new Object();
    static Object o2 = new Object();

    public DeadLockDemo(boolean flag) {
     this.flag = flag;
    }

    @Override
    public void run() {

        //1、如果flag为真,线程A就会得到/持有o1对象锁,然后尝试去获取o2对象锁
        //2、如果线程A得不到o2对象锁,就会block
        //3、如果flag为假,线程B就会得到/持有o2对象锁,然后尝试去获取o1对象锁
        //4、如果线程B德不到o1对象锁,就会block
        if (flag) {
            synchronized (o1) {//对象互斥锁,下面是同步代码
                System.out.println(Thread.currentThread().getName() + " 进入1");
                synchronized (o2) {//这里获得li对象监视权
                    System.out.println(Thread.currentThread().getName() + " 进入2");
                }
            }
        } else {
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName() + "进入3");
                synchronized (o1) {
                    System.out.println(Thread.currentThread().getName() + "进入4");
                }
            }
        }
    }
}

释放锁

多线程练习题一

package com.ThreadHomework;

import javax.swing.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
import java.util.Scanner;
public class Homework01 {

    public static void main(String[] args) {
        A a = new A();
        a.start();
        B b = new B(a);
        b.start();
    }
}

class A extends Thread {

    boolean loop = true;

    @Override
    public void run() {
        while (loop) {
            Random r = new Random();
            System.out.println(r.nextInt(100));
            try {
                Thread.sleep(1000);

            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }
}

class B extends Thread {

    private A a;
    private Scanner scanner = new Scanner(System.in);
    public B(A a) {//构造器中,直接传入A类对象,从而控制A
        this.a = a;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println("请输入你的指令Q");
            char key = scanner.next().toUpperCase().charAt(0);
            if (key =='Q' ){
                a.setLoop(false);
                System.out.println("输入了Q退出");
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

 

多线程练习题二

 

package com.ThreadHomework;

import com.polymorphic_多态.example.转型.Cat;

public class Hoemwork02 {
    public static void main(String[] args) {

        Money money = new Money();
        Thread thread01 = new Thread(money);
        Thread thread02 = new Thread(money);
        thread01.setName("用户1");
        thread01.start();
        thread02.setName("用户2");
        thread02.start();

    }
}

//涉及到多个线程共享资源的方式,使用Runnable的方式
class Money implements Runnable {
    private int cash = 10000;

    @Override
    public void run() {
        while (true) {

            //1.这里使用 实现了线程同步
            //2.当多个线程执行到这里时,就会争夺this对象锁
            //3.哪个线程争夺到(获取)到this对象的锁,就执行synchronized 代码块,执行完后,会释放this对象锁
            //4.争夺不到this对象锁,就blocked,准备继续争夺
            //5.this对象锁是非公平锁
            synchronized (this) {
                if (cash > 0) {
                    System.out.println(Thread.currentThread().getName() + "取出了1000元" + (cash = cash - 1000));
                } else if (cash <= 0) {
                    System.out.println(Thread.currentThread().getName() + "钱已取完了");
                    break;
                }
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }
    }
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值