0


创建一个线程——— Javaweb (3)

1.创建线程的方式

(1)通过显示继承thread类的方式来实现

Thread t1=new Thread(){
            @Override
            public void run() {
                System.out.println(1);
            }
        };

    t1.start();

(2)通过显示创建一个类,实现Runnable接口,然后再把这个runnable的实例关联到Thread的实例上


public class Hello {
    static class myrunnable implements Runnable
    {
        public void run()
        {
            System.out.println("我是线程");
        }
    }
    public static void main(String[] args) throws InterruptedException{
        Thread t1=new Thread(new myrunnable());
        t1.start();
}}

3 通过匿名内部类的方式创建一个线程


public class Hello {
    public static void main(String[] args) throws InterruptedException{
       Runnable myrunnable=new Runnable(){
           public void run() {
               System.out.println("我是一个线程");
           }
       };
       Thread t1=new Thread(myrunnable);
       t1.start();

    }}

4 通过lamda的表达式的方式创建一个线程


public class Hello {
    public static void main(String[] args) throws InterruptedException{
    Thread t1=new Thread(()->{System.out.println("我是一个线程");});
    t1.start();

    }}

面试题:thread类中的run与start方法中的区别

答:调用start方法可以直接启动线程,并使线程进入就绪,当run方法执行完了,线程,也就结束了。但是如果直接执行run方法,会当作普通方法来调用,不会创建一个新线程;

2.为了理解多线程和join的用法,来写几个代码看看

1.我们先看单线程的执行效果


public class Hello {
    public static void main(String[] args){
    long beg1=System.currentTimeMillis();
    int a=0;
    for(long i=0;i<1000000000;i++)
    {
        a++;

    }
    int b=0;
    for(int j=0;j<1000000000;j++)
    {
        b++;
    }
    long beg2=System.currentTimeMillis();
    System.out.println("执行时间为");
        System.out.println(beg2-beg1);
    }}

576

2 再看多线程的执行效果

  class Hello{
    public static void main(String[] args) throws InterruptedException{
        long beg1=System.currentTimeMillis();
        Thread t1=new Thread(){
            public void run(){
              long a=0;
          for(long i=0;i<1000000000;i++)
            {
                a++;
            }
            }
        };
        Thread t2=new Thread(){
            public void run(){
            long b=0;
            for(long j=0;j<1000000000;j++)
            {
                b++;
            }
        }
    };
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        long beg2=System.currentTimeMillis();
        System.out.println("执行时间为");
        System.out.println(beg2-beg1);

    }
}
374

由此我们可知:多线程会比单线程效率更高

join作用是:让线程1****和线程二执行完毕后再执行主线程(没加join之前,线程1,线程2,和主线程是同时执行的);也就是说 此时的join是让主线程阻塞,t1,t2是并发执行的

但是如果这样

t1.start();
t1.join();
t2.start();
t2.join();

**这时 **t1,t2 是串行执行的。

3.其他内容补充:

1,主线程还是一直向下走,但是新线程会执行RUN方法,对于主线程来说,run方法执行完了,新线程就结束了,对于主线程来说,main方法执行完,主线程就结束了

2,线程之间,是并发执行的关系,谁先执行,谁后执行,谁执行到哪里让出CPU,都是不确定的,作为程序员是无法感知的,全权有操作系统的内核负责。例如当创建一个新线程的时候,接下来是主线程先执行,还是新线程,是不好保证的。

3.执行join方法的时候,该线程会一直阻塞,一直阻塞到对应线程结束后,才会继续执行,本质上来说是为了控制线程执行的先后顺序,而对于sleep来说,谁调用谁就会阻塞;

4,主线程把任务分成几份,每个线程计算自己的一份任务,当所有的任务被计算完毕后,主线程再来汇总(就必须保证主线程是最后执行完的线程)。

5 获得当前对象的引用 Thread.currentThread()

6 如果线程正在运行,执行计算其逻辑,此时就在就绪队列排序呢,调度器就会在就绪队列找出合适的PCB让他在CPU执行,如果某个线程调用Sleep就会让对应的PCB进入阻塞队列,无法上CPU;

7 对于sleep让其进入阻塞队列的时间是有限制的,时间到了之后,就会被系统把PCB那回到原来的就绪队列中了;

8 join被恢复的条件是对应的线程结束。


本文转载自: https://blog.csdn.net/weixin_61518137/article/details/123422040
版权归原作者 小比特大梦想 所有, 如有侵权,请联系我们删除。

“创建一个线程&mdash;&mdash;&mdash; Javaweb (3)”的评论:

还没有评论