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

线程组成

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

  1. CPU时间片:操作系统(OS)会为每个线程分配执行时间。

  2. 运行数据:

    • 堆空间:存储线程需使用的对象,多个线程可以共享堆中的对象。
    • 栈空间:存储线程需使用的局部变量,每个线程都拥有独立的栈。
  3. 线程的逻辑代码。

线程特点

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

创建线程

创建线程三种方式:

  1. 继承Thread类,重写run方法【重点】
  2. 实现Runnable接口【重点】
  3. 实现Callable接口(后面再讲)

创建线程(一)

第一种方式:

  1. 第一步,继承Thread类,
  2. 第二步,重写run()方法,在run()方法内编写功能代码
  3. 第三步,创建线程对象(new)
  4. 第四步,调用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
*/

获取和修改线程名称

  1. 获取线程ID和线程名称:
    • 在Thread的子类中调用this. getId ()或this. getName () (只适合在继承了Thread的类中使用
    • 使用Thread. currentThread(). getId()和Thread. currentThread (). getName () (在哪都能用)
  2. 修改线程名称:(只能修改线程名称,在线程启动之前修改)
    • 调用线程对象的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();
    }
}

创建线程(二)

第二种方式:

  1. 第一步:定义一个类,实现Runnable接口
  2. 第二步,覆盖run()方法,在run()方法内编写功能代码
  3. 第三步,创建实现类对象(new)
  4. 第四步,创建线程对象(new),把实现类对象传递给线程对象(这个方法可以同时传递线程名称)
  5. 第五步,调用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();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悬浮海

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值