多线程一些基础实现

继承Thread类方式

成都创新互联是一家专注于网站设计制作、成都做网站与策划设计,永善网站建设哪家好?成都创新互联做网站,专注于网站建设10年,网设计领域的专业建站公司;建站业务涵盖:永善等地区。永善做网站价格咨询:18982081108

1. 线程启动时:一定是调用Thread类的start()方法,因为通过源码解析发现,start()方法中,最后会调用以native关键字修饰的start0()方法,该方法会通过JVM实现不同操作系统不同实现的

   资源调度分配;

2. Native关键字:调用本机的操作系统函数。


实现Runnable接口方式

1. 实现Runnable接口:由于继承Thread类会造成单继承的局限性,所以利用接口来实现;

2. Runnable接口:因为其是函数式接口,所以该接口中只有一个方法,可以使用Lamda表达式完成;

3. @FunctionalInterface:修饰的接口为函数式接口;

4. 由于启动发多线程只能通过start()方法,但Runnable方法中没有此方法,故实现该接口并启动一个线程,是通过Thread的构造函数发现:

  public Thread(Runnable targer) ,所以可以通过此方式来启动一个多线程;


实例:Runnnable接口方式

public class Test11 {

    public static void main(String[] args) {
        Test11Demo t1 = new Test11Demo("线程1");
        Test11Demo t2 = new Test11Demo("线程2");
        Test11Demo t3 = new Test11Demo("线程3");
        new Thread(t1).start();
        new Thread(t2).start();
        new Thread(t3).start();
    }

}

class Test11Demo implements Runnable {
    
    private String name;
    
    Test11Demo(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        for (int x = 0; x < 10; x++) {
            System.out.println(this.name + ",x=" + x);
        }
    }
    
}


实例:Lamda方式,内部类方式

在原来代码基础上,添加测试代码

public static void main(String[] args) throws Exception {
    Test11Demo t1 = new Test11Demo("线程1");
    Test11Demo t2 = new Test11Demo("线程2");
    Test11Demo t3 = new Test11Demo("线程3");
    new Thread(t1).start();
    new Thread(t2).start();
    new Thread(t3).start();

    final String name1 = "Lamda测试";
    new Thread( ()->{
        for (int x = 0; x < 10; x++) {
            System.out.println(name1 + ",x=" + x);
        }
    }).start();


    final String name = "内部类测试";
    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int x = 0; x < 10; x++) {
                System.out.println(name + ",x=" + x);
            }
        }
    }).start();
}


两种方式,启动线程的异同

1. 查看源码可知,Thread类定义:

   public classThread extends Object implementsRunnable

2.类关系图:

多线程一些基础实现


综上,可知,

多线程需要一个线程主类:可以继承Thread类,也可以实现Runnable接口;

使用Runnable接口,可以更好的实现数据共享的操作;并可以避免Thread类带来的单继承局限性;


线程的命名和取得

1. 线程的所有操作方法基本上都已经在Thread类中定义完整;

2. 如下方法,可提供线程名称操作:

① 构造方法:public Thread(Runnable target,String name)

② 设置名字:public final void setName(String name)

③ 获取名字:public final String getName()

④ 由于线程执行本身不确定状态,

提供方法:public static Thread currentThread()来取得当前线程

3. 如果在设置线程对象名称时,没有设置具体名字,则会采用默认名字进行定义;

4. 每一个JVM至少会启动两个线程:主线程,GC线程;


线程的休眠

休眠方法:sleep();线程的睡眠,是有先后顺序的

线程的优先级

1. 优先级操作方法:

设置优先级:public final void setPriority(int newPriority);

取得优先级:public final int getPriority();

2. 优先级相关常量:

   最高优先级:public final static int MAX_PRIORITY = 10;

   中等优先级:public final static int NORM_PRIORITY = 5;

   最低优先级:public final static int MIN_PRIORITY = 1;

3.  理论上,会根据设置的优先级进行线程的启动运行;

   主线程,属于一般优先级。


线程的同步与死锁

1. 同步问题的引出:多个线程需要访问统一资源;

2. 同步代码块执行效率要低于异步,同步代码块使用:synchronized关键字

3. 异步执行效率高,但数据不准确;同步代码执行效率慢,但会保证数据的有效性,同时线程安全。

4. 死锁:(了解) 如果程序中出现过多同步,将会产生死锁问题;



---下一篇,线程中的生产者与消费者理解--线程的应用场景之一




文章标题:多线程一些基础实现
链接URL:http://hbruida.cn/article/geecdj.html