多线程中的常用成员方法

多线程中的常用成员方法

String getName() 返回此线程的名称

void setName(String name) 设置线程的名称 (构造方法也可以设置名称)

static Thread currentThread() 获取当前线程的对象

static void sleep(long time) 让当前线程休眠指定的毫秒数

setPriority(int newPriority) 设置线程的优先级*
final int getPriority()* 获取线程的优先级

package xyz.dimeng.m04threadmethod1;

public class MyThread extends Thread{
    public MyThread() {
    }

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

    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            System.out.println(getName()+"-"+i);
        }
    }
}
package xyz.dimeng.m04threadmethod1;

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        /***
        * String getName()                 返回此线程的名称
         * void setName(String name)       设置线程的名称 (构造方法也可以设置名称)
        * 1.如果我们没有给线程设置名称,线程也是有默认的名字的 格式:Thread-X (X序号,从0开始)
        * 2.如果我们要给线程设置名字 可以用set方法设置也可以用构造方法设置
        *
        * static Thread currentThread() 获取当前线程的对象
         * 当jvm虚拟机启动之后,会自动的启动多条线程
         * 其中有一条线程就叫main线程 作用就是调用main方法并执行里面的代码
         * static void sleep(long time)    让当前线程休眠指定的毫秒数
        */
        MyThread t1 = new MyThread("main");
        MyThread t2 = new MyThread("sub");
        t1.start();
        t2.start();
//        Thread t = Thread.currentThread();
//        String name = t.getName();
//        System.out.println(name);
//        System.out.println("---------");
//        Thread.sleep(5000);
//        System.out.println("=============");
    }
}
package xyz.dimeng.m05threadmethod2;

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i <= 100; i++) {

            System.out.println(Thread.currentThread().getName()+"-"+i);
        }
    }
}
package xyz.dimeng.m05threadmethod2;

public class ThreadDemo {
    public static void main(String[] args) throws InterruptedException {
        /***
        * setPriority(int newPriority) 设置线程的优先级
        * final int getPriority() 获取线程的优先级
        *   不是绝对的 概率问题
        */
        MyRunnable mr = new MyRunnable();
        Thread t1 = new Thread(mr,"main");
        Thread t2 = new Thread(mr,"sub");
        /*System.out.println(t1.getPriority());
        System.out.println(t2.getPriority());
        System.out.println(Thread.currentThread().getPriority());*/
        t1.setPriority(1);
        t2.setPriority(10);
        t1.start();
        t2.start();
    }
}

final void setDaemon(boolean on) 设置为守护线程

package xyz.dimeng.m06threadmethod3;

public class ThreadDemo {
    public static void main(String[] args){
        /***
        * final void setDaemon(boolean on) 设置为守护线程
         * 当其他的非守护线程执行完毕之后,守护线程会陆续结束
         * (应用场景 聊天时候传输文件 传输文件的线程设置为守护线程)
        */
        MyThread1 t1 = new MyThread1();
        MyThread2 t2 = new MyThread2();
        t1.setName("sub");
        t2.setName("main");
        t2.setDaemon(true);
        t1.start();
        t2.start();
    }
}

package xyz.dimeng.m06threadmethod3;

public class MyThread1 extends Thread{
    @Override
    public void run() {

        for (int i = 0; i < 10; i++) {
            System.out.println(getName()+"-"+i);
        }
    }
}

package xyz.dimeng.m06threadmethod3;

public class MyThread2 extends Thread{
    @Override
    public void run() {

        for (int i = 0; i < 100; i++) {
            System.out.println(getName()+"-"+i);
        }
    }
}

public static void yield() 出让线程*/*礼让线程

public final void join() 插入线程*/*插队线程

线程的生命周期

image-20240508124230566

线程的安全问题

案例:火车站卖100张票 三个窗口

在Java中,synchronized关键字用于实现同步,确保多个线程不会同时访问共享资源,从而避免竞态条件和数据不一致性的问题。当使用synchronized关键字时,可以指定一个对象作为锁。在这种情况下,当一个线程获得了该对象的锁时,其他线程就无法同时获得该对象的锁,从而确保了同步。

在Java中,每个类在内存中都有一个对应的Class对象,而且每个类的Class对象在整个JVM中都是唯一的。因此,使用类的字节码对象作为锁对象是安全的,因为它是唯一的,可以确保在多线程环境下的同步。

package xyz.dimeng.m09threadsafe1;

public class MyThread extends Thread{
    //表示这个类所有的对象,都共享ticket数据
    static int ticket = 0;

    //锁对象,一定是唯一的
    static Object obj = new Object();
    @Override
    public void run() {
        while (true){
            //同步代码块
            //synchronized (obj){
            synchronized (MyThread.class){
                if(ticket<100){
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    ticket++;
                    System.out.println(getName()+"正在卖第"+ticket+"张票");
                }else {
                    break;
                }
            }
        }
    }
}

package xyz.dimeng.m09threadsafe1;

public class ThreadDemo {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

单线程不需要考虑线程安全用StringBuilder

多线程用StingBuffer

同步方法

就是把synchronized关键字加到方法上

特点1:同步方法是锁住方法里面所有的代码

特点2:锁对象不能自己指定(非静态:this,静态:当前类的字节码文件对象)

package xyz.dimeng.m10threadsafe2;

import xyz.dimeng.m09threadsafe1.MyThread;

public class ThreadDemo {
    public static void main(String[] args) {
        //利用同步方法完成保证多线程安全
        MyRunnable mr = new MyRunnable();
        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);
        Thread t3 = new Thread(mr);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

package xyz.dimeng.m10threadsafe2;

public class MyRunnable implements Runnable {
    int ticket = 0;

    @Override
    public void run() {
        //1.循环
        //2.同步代码块(同步方法)
        //3.判断共享数据是否到了末尾,如果到了末尾
        //4.判断共享数据是否到了末尾,如果没有到末尾
        while (true) {
            if (method()) {
                break;
            }
        }
    }

    //非静态 锁对象 this
    private synchronized boolean method() {
        if (ticket == 100) {
            return true;
        } else {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            ticket++;
            System.out.println(Thread.currentThread().getName() + "在卖:" + ticket + "张票");
        }
        return false;
    }
}

这个错误提示说明你尝试将一个 `List<List<Object & Serializable & Comparable<?>>>` 类型的对象转换为 `List<List<Object>>` 类型的对象,但是这两个类型不兼容。 `List<List<Object & Serializable & Comparable<?>>>` 类型表示一个元素类型为 `List`,其中每个元素又是一个元素类型为 `Object`、`Serializable` 和 `Comparable` 的对象的列表。而 `List<List<Object>>` 类型表示一个元素类型为 `List`,其中每个元素又是一个元素类型为 `Object` 的对象的列表。 由于 `Object & Serializable & Comparable<?>` 比 `Object` 类型更加具体,所以 `List<List<Object & Serializable & Comparable<?>>>` 类型的对象不能直接转换为 `List<List<Object>>` 类型的对象,因为前者包含了更多的信息。 如果你需要将 `List<List<Object & Serializable & Comparable<?>>>` 类型的对象转换为 `List<List<Object>>` 类型的对象,你可以考虑先将其中每个元素中的 `Object & Serializable & Comparable<?>` 类型的对象转换为 `Object` 类型的对象,再将整个列表转换为 `List<List<Object>>` 类型的对象。例如: ```java List<List<Object & Serializable & Comparable<?>>> list1 = ...; List<List<Object>> list2 = new ArrayList<>(); for (List<Object & Serializable & Comparable<?>> innerList : list1) { List<Object> convertedInnerList = new ArrayList<>(); for (Object & Serializable & Comparable<?> obj : innerList) { convertedInnerList.add((Object) obj); // 将 Object & Serializable & Comparable<?> 类型的对象转换为 Object 类型的对象 } list2.add(convertedInnerList); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

抵梦

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

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

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

打赏作者

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

抵扣说明:

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

余额充值