Java基础:多线程

创造多线程的方法之一:

/**
 *
 * 多线程的创建
 * 方法一:继承于Thread类
 * 1、创建一个继承于Thread类的子类
 * 2、重写Thread类的run() --> 将此线程执行的操作声明在run()中
 * 3、创建Thread类的子类的对象
 * 4、通过此对象调用start()
 *
 * 例子:遍历100以内的所有偶数
 *
 *
 * @author shkstart
 * @create 2021-01-24 20:00
 */

//1、创造一个继承于Thread类的子类
class MyThread extends Thread{

    //2、重写Thread类的run()
    @Override
    public void run() {
        for(int i = 0 ; i <100 ; i++){
            if(i%2 == 0){
                System.out.print(i + " ");
            }
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {

        //3、创建Thread类的子类的对象
        MyThread t1 = new MyThread();

        //4、通过此对象调用start()
        t1.start();

        //多线程的表示:与t1.start()的结果交叉执行⭐
        for(int i = 0 ; i <100 ; i++){
            if(i%2 == 0){
                System.out.print(i + "***** main() ");
            }
        }
    }
}

创建过程中两个问题的说明

//1、创造一个继承于Thread类的子类
class MyThread extends Thread{

    //2、重写Thread类的run()
    @Override
    public void run() {
        for(int i = 0 ; i <100 ; i++){
            if(i%2 == 0){
                //System.out.print(i + " ");
                System.out.println(Thread.currentThread().getName() + ":");
            }
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {

        //3、创建Thread类的子类的对象
        MyThread t1 = new MyThread();


        //14、创建过程中两个问题的说明

        //4、通过此对象调用start()
        /*
		⭐
        //问题二:
        start()方法的作用
        1、启动当前线程
        2、调用当前线程的run()

         */
        //start表示新建一个线程
        t1.start();//Thread.currentThread().getName():Thread

        t1.run();//Thread.currentThread().getName():main
		//⭐
        //问题二 : 再启动一个线程,遍历100以内的偶数
        t1.start();//Exception in thread "main" java.lang.IllegalThreadStateException
        MyThread t2 = new MyThread();
        t2.start();


        //多线程的表示:与t1.start()的结果交叉执行
        //如下的操作仍然在main线程中执行的
        for(int i = 0 ; i <100 ; i++){
            if(i%2 == 0){
                //System.out.print(i + "***** main() ");
                System.out.println(Thread.currentThread().getName() + ":");
            }
        }
    }
}

练习1:

package com.atguigu.exer;

/**
 * 练习:
 * 创建两个分线程
 * 其中一个线程遍历100以内的偶数
 * 另一个线程遍历100以内的奇数
 *
 *
 * @author shkstart
 * @create 2021-01-24 20:41
 */


public class ThreadDemo15 {
    public static void main(String[] args) {
//        MyThread1 t1 = new MyThread1();
//        t1.start();
//        MyThread2 t2 = new MyThread2();
//        t2.start();

        /*
        
        方法二:
        
         */
        //创建Thread类的匿名子类的方式
        new Thread(){
            @Override
            public void run() {
                for(int i = 0 ; i < 100 ; i++) {
                    if(i % 2 == 0){
                        System.out.println(i + Thread.currentThread().getName());
                    }
                }
            }
        }.start();

        new Thread(){
            @Override
            public void run() {
                for(int i = 0 ; i < 100 ; i++) {
                    if(i % 2 != 0){
                        System.out.println(i + Thread.currentThread().getName());
                    }
                }
            }
        }.start();

    }
}

//方法1:造两个类
class MyThread1 extends Thread{
    @Override
    public void run() {
        for(int i = 0 ; i < 100 ; i++) {
            if(i % 2 == 0){
                System.out.println(i + Thread.currentThread().getName());
            }
        }
    }
}

class MyThread2 extends Thread{
    @Override
    public void run() {
        for(int i = 0 ; i < 100 ; i++) {
            if(i % 2 != 0){
                System.out.println(i + Thread.currentThread().getName());
            }
        }
    }
}



Thread类的常用方法

package com.atguigu.java;

/**
 *
 * Thread类的常用方法:
 * 1 void start(): 启动线程,并执行对象的run()方法
 *
 * 2 run(): 线程在被调度时执行的操作
 *      通常需要重写Thread类中的此方法,讲创建的线程要执行的操作声明在此方法中
 *
 * 3 String getName(): 返回线程的名称
 *
 * 4 void setName(String name):设置该线程名称
 *
 * 5 static Thread currentThread(): 返回当前线程。在Thread子类中就是this,通常用于主线程和Runnable实现类
 *
 * 6 static void yield():线程让步
 *      暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程
 *      若队列中没有同优先级的线程,忽略此方法
 *
 * 7 join() :当某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止
 *      低优先级的线程也可以获得执行
 *      当线程 a 中 执行 b.join()方法那么直到 b 执行结束之后 a才开始执行
 *
 * 8 static void sleep(long millis):(指定时间:毫秒) 令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队。
 *      抛出InterruptedException异常
 *
 * 9 stop(): 强制线程生命期结束,不推荐使用
 *      已经过时
 *      用 sleep()来代替
 *      sleep(i) 表示线程堵塞 i 秒
 *
 * 10 boolean isAlive():返回boolean,判断线程是否还活着
 *
 * @author shkstart
 * @create 2021-01-24 21:05
 */
public class ClassThreadMeans16 {
    public static void main(String[] args) {
        //通过setName()命名
        HelloThread t1 = new HelloThread("Thread: 1");
        t1.setName("线程一");
        t1.start();

        //通过构造器命名
        HelloThread t2 = new HelloThread("Thread: 2");
        t2.start();

        //给主线程命名
        Thread.currentThread().setName("主线程");
        for(int i = 1 ; i < 50 ; i++){//主线程主导
            if(i % 2 == 0 ){
                System.out.println(i + Thread.currentThread().getName());
            }
//join()测试
            if(i == 20){
                try {
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            if(i == 20){
                try {
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }


    }
}

class HelloThread extends Thread{
    @Override
    public void run() {
        for(int i = 1 ; i < 50 ; i++){
            if(i % 2 == 0 ){
//sleep()测试

                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(i + Thread.currentThread().getName());
            }



//yield()测试
            //this代表HelloThread的对象
            if(i % 20 == 0){

                //yield()表示 : 释放当前线程,让另一个线程工作
            this.yield();
            //yield();

        }
        }
    }

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

}

线程优先级的设置

package com.atguigu.java;

/**
 *
 * 线程的优先级
 * 1、
 * MAX_PRTORITY:10
 * MIN_PRIORITY:1
 * MORM_PRIORITY:5
 *
 * 2、如何获取和设置当前线程的优先级
 *      getPriority();
 *      setPriority(int p);
 *
 * 高优先级只是可能先执行,但是并不是先执行
 *
 * @author shkstart
 * @create 2021-01-24 21:56
 */
public class Thread17 {
    public static void main(String[] args) {
        Thread3 t3 = new Thread3();
        //在运行之前设置线程的优先级
        t3.setPriority(Thread.MAX_PRIORITY);
        t3.start();

        for(int i = 1; i < 50; i++) {
            if (i % 2 == 0) {
                System.out.println(i + Thread.currentThread().getName() + "、" + Thread.currentThread().getPriority());
            }
        }

    }

}


class Thread3 extends Thread {
    @Override
    public void run() {
        for (int i = 1; i < 50; i++) {
            if (i % 2 == 0) {
                System.out.println(i + Thread.currentThread().getName() + "、" + Thread.currentThread().getPriority());
            }
        }
    }
}

练习2

package com.atguigu.exer;

import sun.applet.Main;

import java.awt.*;

/**
 * 例子:创建三个窗口买票,总票数为100张
 *
 *
 * @author shkstart
 * @create 2021-01-24 22:25
 */
public class Thread18 {
    public static void main(String[] args) {
        window w1 = new window();
        window w2 = new window();
        window w3 = new window();

        w1.setName("窗口1");
        w2.setName("窗口2");
        w3.setName("窗口3");

        w1.start();
        w2.start();
        w3.start();
    }


}

class window extends Thread{
    //static 让所有对象共享⭐
    private static int ticket = 100;

    @Override
    public void run() {

        while(true){

            if(ticket > 0){
                System.out.println(getName() + ": 买票,票号为" + ticket);
                ticket--;
            }
            else{
                break;
            }

        }
    }
}

创造多线程的方法之二:实现Runnable接口

package com.atguigu.java;

/**
 * 创造多线程的方法之二:实现Runnable接口
 * 1、创建一个实现了Runnable接口的类
 * 2、实现类去实现Runnable中的抽象方法:run()
 * 3、创造实现类的对象
 * 4、将此对象作为参数传递到Thread类的构造器中,创造Thread类的对象
 * 5、通过Thread类的对象调用start()
 *
 * @author shkstart
 * @create 2021-01-24 22:40
 */
public class Thread19 {
    public static void main(String[] args) {
        //3、创造实现类的对象
        Thread4 mThread = new Thread4();
        //4、将此对象作为参数传递到Thread类的构造器中,创造Thread类的对象
        Thread t1 = new Thread(mThread);
        //5、通过Thread类的对象调用start()
        t1.start();

        //再启动一个线程
        Thread t2 = new Thread(mThread);
        t2.start();
    }
}
//1、创建一个实现了Runnable接口的类
class Thread4 implements Runnable{
//2、实现类去实现Runnable中的抽象方法:run()
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            if(i % 2 == 0){
                System.out.println(Thread.currentThread().getName()+ ":" + i);
            }
        }
    }
}

练习3

package com.atguigu.exer;

/**
 * @author shkstart
 * @create 2021-01-24 23:34
 */
public class Thread20 {
    public static void main(String[] args) {
        myThread mthread = new myThread();
        Thread t1 = new Thread(mthread);
        t1.setName("1");
        Thread t2 = new Thread(mthread);
        t2.setName("2");
        Thread t3 = new Thread(mthread);
        t3.setName("3");

        t1.start();
        t2.start();
        t3.start();
    }

}

class myThread implements Runnable{
    private int ticket = 100;

    @Override
    public void run() {
        while(true){
            if(ticket > 0){
                System.out.println("窗口" + Thread.currentThread().getName() + "卖票:剩余票数" + ticket);
                ticket--;
            }
            else{
                break;
            }
        }
    }
}

两种方式的对比

在开发中:优先选择实现Runnable接口的方式
原因:
1、实现方式没有继承类的局限性
2、实现的方式更适合来处理多个线程有共享数据的情况。

联系:public class Thread implements Runnable

相同点:两种方式都需要重写run(),将线程要执行的逻辑声明在run()中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值