当前位置 : 主页 > 编程语言 > java >

70 java多线程_2 _线程的组成与创建线程

来源:互联网 收集:自由互联 发布时间:2022-07-13
文章目录 ​​线程组成​​ ​​线程特点​​ ​​创建线程​​ ​​创建线程(一)​​ ​​第一种方式:​​ ​​获取和修改线程名称​​ ​​卖票案例​​ ​​创建线程(二


文章目录

  • ​​线程组成​​
  • ​​线程特点​​
  • ​​创建线程​​
  • ​​创建线程(一)​​
  • ​​第一种方式:​​
  • ​​获取和修改线程名称​​
  • ​​卖票案例​​
  • ​​创建线程(二)​​
  • ​​第二种方式:​​
  • ​​补充使用匿名内部类:​​
  • ​​Runnable案例1:​​
  • ​​Runnable案例2:​​

线程组成

任何一个线程都具有基本的组成部分:

  • CPU时间片:操作系统(OS)会为每个线程分配执行时间。
  • 运行数据:
    • 堆空间:存储线程需使用的对象,多个线程可以共享堆中的对象。
    • 栈空间:存储线程需使用的局部变量,每个线程都拥有独立的栈。
  • 线程的逻辑代码。
  • 线程特点

  • 线程抢占式执行:
    • 效率高
    • 可防止单一线程长时间独占CPU
  • 在单核CPU中,宏观上同时执行,微观上顺序执行。
  • 创建线程

    创建线程三种方式:

  • 继承Thread类,重写run方法【重点】
  • 实现Runnable接口【重点】
  • 实现Callable接口(后面再讲)
  • 创建线程(一)

    第一种方式:

  • 第一步,继承Thread类,
  • 第二步,重写run()方法,在run()方法内编写功能代码
  • 第三步,创建线程对象(new)
  • 第四步,调用start()方法,这个方法是启动线程(不能调用run()方法,因为这相当于调用普通对象的一个普通方法)
  • 创建线程的代码:

    package com.wlw.thread;

    /**
    * 线程类
    * 创建线程的第一种方式
    */
    public class MyThread extends Thread{ //第一步,继承Thread类,
    @Override
    public void run() { //第二步,重写run()方法,在run()方法内编写功能代码
    for (int i = 0; i < 2000; i++) {
    System.out.println("子线程-------------"+i);
    }
    }
    }package com.wlw.thread;

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

    //第三步,创建线程对象(new)
    MyThread myThread = new MyThread();

    //第四步,调用start()方法,这个方法是启动线程
    myThread.start();

    //主线程执行
    for (int i = 0; i < 2000; i++) {
    System.out.println("主线程----------------------"+i);
    }
    }
    }
    //循环次数过小,可能出现运行结果不符合理想,总是一个线程执行完,再执行另一个线程,此时就加大循环次数,应该就会出现理想结果,如下:(部分执行结果)
    /*
    子线程-------------241
    主线程----------------------261
    子线程-------------242
    主线程----------------------262
    子线程-------------243
    主线程----------------------263
    主线程----------------------264
    主线程----------------------265
    子线程-------------244
    子线程-------------245
    子线程-------------246
    主线程----------------------266
    子线程-------------247
    子线程-------------248
    子线程-------------249
    */

    获取和修改线程名称

  • 获取线程ID和线程名称:
    • 在Thread的子类中调用this. getId ()或this. getName () (只适合在继承了Thread的类中使用)
    • 使用Thread. currentThread(). getId()和Thread. currentThread (). getName ()(在哪都能用)
  • 修改线程名称:(只能修改线程名称,在线程启动之前修改)
    • 调用线程对象的setName()方法(创建完对象,再调用setName())
    • (建议使用)使用线程子类的构造方法赋值(在带参构造方法中,调用父类Thread的带参构造,super(name))

    代码:

    package com.wlw.thread;

    /**
    * 线程类
    * 创建线程的第一种方式
    */
    public class MyThread extends Thread{ //第一步,继承Thread类,


    public MyThread() {
    }
    public MyThread(String name){
    super(name);
    }

    @Override
    public void run() { //第二步,重写run()方法,在run()方法内编写功能代码
    for (int i = 0; i < 2000; i++) {
    //第一种方式:在Thread的子类中调用this. getId ()或this. getName () (只适合在继承了Thread的类中使用)
    //System.out.println("线程ID:"+this.getId()+"线程名称:"+this.getName()+",子线程-------------"+i);

    //第二种方式:使用Thread. currentThread() 获取当前线程
    System.out.println("线程ID:"+Thread.currentThread().getId() +"线程名称:"+Thread.currentThread().getName() +",子线程-------------"+i);
    }
    }
    }package com.wlw.thread;

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

    //第三步,创建线程对象(new)
    MyThread myThread01 = new MyThread("我的子线程1");

    //修改线程名称,setName()
    //thread_demo01.setName("我的子线程1");

    //第四步,调用start()方法,这个方法是启动线程
    myThread01.start();

    MyThread myThread02 = new MyThread("我的子线程2");
    //thread_demo02.setName("我的子线程2");
    myThread02.start();

    //主线程执行
    for (int i = 0; i < 2000; i++) {
    System.out.println("主线程----------------------"+i);
    }
    }
    }

    卖票案例

    /**
    *使用继承Thread类实现4个窗口各卖100张票
    */
    package com.wlw.thread;

    /**
    * 卖票窗口类(继承类)
    */
    public class TickeWin extends Thread {

    public TickeWin(){
    }

    public TickeWin(String name){
    super(name);
    }

    @Override
    public void run() {
    //买票功能
    for (int i = 1; i <= 100; i++){
    System.out.println("ID:"+Thread.currentThread().getId()+","+Thread.currentThread().getName()+",卖出了第"+i+"张票");
    }

    /* int ticket = 100;//票
    while (true){
    if(ticket <= 0){
    break;
    }
    System.out.println(Thread.currentThread().getName()+",卖出了第"+ticket+"张票");
    ticket--;
    }*/
    }
    }package com.wlw.thread;

    public class TestWin {
    public static void main(String[] args) {
    //创建四个对象
    TickeWin tickeWin1 = new TickeWin("窗口1");
    TickeWin tickeWin2 = new TickeWin("窗口2");
    TickeWin tickeWin3 = new TickeWin("窗口3");
    TickeWin tickeWin4 = new TickeWin("窗口4");

    //启动线程
    tickeWin1.start();
    tickeWin2.start();
    tickeWin3.start();
    tickeWin4.start();
    }
    }

    创建线程(二)

    第二种方式:

  • 第一步:定义一个类,实现Runnable接口
  • 第二步,覆盖run()方法,在run()方法内编写功能代码
  • 第三步,创建实现类对象(new)
  • 第四步,创建线程对象(new),把实现类对象传递给线程对象(这个方法可以同时传递线程名称)
  • 第五步,调用start()方法,这个方法是启动线程
  • 代码:

    package com.wlw.thread;
    /**
    * 线程类
    * 创建线程的第二种方式
    */
    public class MyRunnable implements Runnable{ //第一步:定义一个类,实现Runnable接口
    @Override
    public void run() { //第二步,覆盖run()方法,在run()方法内编写功能代码
    for (int i = 0; i < 2000; i++) {
    System.out.println(Thread.currentThread().getName()+",子线程---------------"+i);
    }
    }
    }package com.wlw.thread;

    public class TestRunnable {
    public static void main(String[] args) {
    //第三步,创建实现类对象(new)
    //创建MyRunnable对象,表示线程要实现的功能
    MyRunnable myRunnable = new MyRunnable();

    //第四步,创建线程对象,把实现类对象传递给线程对象
    Thread thread = new Thread(myRunnable,"我的线程");

    //第五步,调用start()方法,这个方法是启动线程
    thread.start();

    for (int i = 0; i < 2000; i++) {
    System.out.println("主线程========================"+i);
    }
    }
    }

    补充使用匿名内部类:

    代码:

    package com.wlw.thread;

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

    /*
    //第三步,创建实现类对象(new)
    //创建MyRunnable对象,表示线程要实现的功能
    MyRunnable myRunnable = new MyRunnable();

    //第四步,创建线程对象,把实现类对象传递给线程对象
    Thread thread = new Thread(myRunnable,"我的线程");

    //第五步,调用start()方法,这个方法是启动线程
    thread.start();
    */

    //使用匿名内部类
    //创建可运行对象,相当于new一个Runnable的子类
    Runnable runnable = new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 2000; i++) {
    System.out.println(Thread.currentThread().getName()+",子线程---------------"+i);
    }
    }
    };
    //创建线程
    Thread thread = new Thread(runnable,"我的匿名内部类的线程");
    thread.start();

    for (int i = 0; i < 2000; i++) {
    System.out.println("主线程========================"+i);
    }
    }
    }

    Runnable案例1:

    四个窗口共卖100张票

    注意:会出现多个窗口卖了同一张票,这是一个线程安全问题,后面解决(!!!!!!!!!!!)

    package com.wlw.thread.caseDemo;

    /**
    * 票类(共享资源)
    */
    public class Ticket implements Runnable{

    int ticket = 100; //票总共100张

    //售票功能
    @Override
    public void run() {
    while (true){
    if(ticket <= 0){
    break;
    }
    System.out.println(Thread.currentThread().getName()+"卖了第"+ticket+"张票");
    ticket--;
    }
    }
    }package com.wlw.thread.caseDemo;

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

    // 创建实现类对象
    Ticket ticket = new Ticket();

    //创建线程对象
    Thread thread1 = new Thread(ticket,"窗口1");
    Thread thread2 = new Thread(ticket,"窗口2");
    Thread thread3 = new Thread(ticket,"窗口3");
    Thread thread4 = new Thread(ticket,"窗口4");

    //调用start()方法,启动线程
    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();

    /*
    会出现多个窗口卖了同一张票,这是一个线程安全问题,后面解决(!!!!!!!!!!!!!!!!)
    */
    }
    }

    Runnable案例2:

    注意:一开始会出现存取钱时,余额显示不准确,这是一个线程安全问题,后面解决(!!!!!!!!!!!)

    package com.wlw.thread.caseDemo;
    /**
    * 银行卡类
    */
    public class BankCard {
    private Double money;

    public Double getMoney() {
    return money;
    }

    public void setMoney(Double money) {
    this.money = money;
    }
    }package com.wlw.thread.caseDemo;
    /**
    * 存钱
    */
    public class AddMoney implements Runnable {

    private BankCard bankCard;
    public AddMoney(BankCard bankCard){
    this.bankCard = bankCard;
    }

    //存钱功能
    @Override
    public void run() {
    for (int i = 0; i < 10; i++) {
    bankCard.setMoney(bankCard.getMoney() + 1000);
    System.out.println(Thread.currentThread().getName()+"存了1000块钱,余额是:"+bankCard.getMoney());
    }

    }
    }package com.wlw.thread.caseDemo;
    /**
    * 取钱
    */
    public class SubMoney implements Runnable {
    private BankCard bankCard;
    public SubMoney(BankCard bankCard){
    this.bankCard = bankCard;
    }

    @Override
    public void run() {
    for (int i = 0; i < 10; i++) {
    if(bankCard.getMoney() >= 1000){
    bankCard.setMoney(bankCard.getMoney()-1000);
    System.out.println(Thread.currentThread().getName()+"取了1000块钱,余额是:"+bankCard.getMoney());
    }else {
    System.out.println("余额不足");
    i--;
    }
    }

    }
    }package com.wlw.thread.caseDemo;

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

    //1.创建银行卡
    BankCard bankCard = new BankCard();
    bankCard.setMoney(0.0);

    //2.创建存取功能对象
    AddMoney addMoney = new AddMoney(bankCard);
    SubMoney subMoney = new SubMoney(bankCard);

    //3.创建线程对象
    Thread thread1 = new Thread(addMoney,"存钱线程");
    Thread thread2 = new Thread(subMoney,"取钱线程");

    //4.启动线程
    thread1.start();
    thread2.start();
    }
    }

    使用匿名内部类:

    package com.wlw.thread.caseDemo;

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

    //1.创建银行卡
    BankCard bankCard = new BankCard();
    bankCard.setMoney(0.0);

    //2.存取功能
    Runnable add = new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 10; i++) {
    bankCard.setMoney(bankCard.getMoney() + 1000);
    System.out.println(Thread.currentThread().getName()+ "存了1000块钱,余额是:" +bankCard.getMoney());
    }
    }
    };
    Runnable sub = new Runnable() {
    @Override
    public void run() {
    for (int i = 0; i < 10; i++) {
    if(bankCard.getMoney() >= 1000){
    bankCard.setMoney(bankCard.getMoney() - 1000);
    System.out.println(Thread.currentThread().getName()+ "取了1000块钱,余额是:" +bankCard.getMoney());
    }else {
    System.out.println("余额不足,请充值");
    i--;
    }

    }
    }
    };

    //3.创建线程对象,并启动
    new Thread(add,"存钱线程").start();
    new Thread(sub,"取钱线程").start();

    }
    }


    网友评论