各位,现在打开你的电脑的任务管理器,你是否会看到你的电脑有很多进程,但你的电脑核心数就只有十几个,那么这些“牛马”是如何同时进行这么多任务的推进呢?方法:分时复用,把一个单位时间分成很多小片,第一片运行进程1中的指令不停的切换运行,cpu运行速度快,超过你的反应时间,给你一种在同时进行的感觉,这种单个cpu执行多个进程的方式也被称为并发执行。【多个cpu核心同时执行多进程的方式,称为并行执行,但我们一般全把它叫为并发执行】。谈到并发,我们不能脱离进程的概念,进程是操作系统资源分配的最小单位,通俗一点来说,进程就是一个运行起来的程序,但是进程之间的资源隔离性强【每个独立的进程都有完全隔离的资源空间,两个进程需要协作,不能直接传递数据,要借助操作系统提供的跨进程通信机制,产生大量的系统调用开销】,通信和切换的成本极高【操作系统的"分时复用"的过程叫进程上下文的切换,该上下文包含进程的所有运行状态信息,切换与加载的过程会消耗大量的cpu资源】。由于进程太“重”,故引入轻量级的进程,也就是线程,线程相比与进程,只有第一个线程的创建申请资源,后续再创建线程,不涉及资源的申请,且只有所有的线程都销毁才真正的释放资源,只销毁某个,不会释放资源。【线程可以资源共享,上下文切换仅需保存少量私有数据,轻量易创建】,对于java程序,默认包含了main主线程,当主线程没办法满足多任务并发执行,我们就需要通过java提供Thread类创建线程,Thread是并发编程中多线程的核心,创建与管理线程也是本文的核心,接下来,您瞧好了。

1.线程创建

        首先,是线程的创建,线程的创建有7种方法,如图:

//1.实现Runnable接口
class B implements Runnable{
        public void run(){
            int i=0;
            while(i<=5) {
                System.out.println("hello,Runnable");
                try{
                    Thread.sleep(1000);
                    i++;
                }catch(InterruptedException e){
                    throw new RuntimeException();
                }
            }
        }
}
public class ThreadTwo {
    public static void main(String[] args){
            Runnable r=new B();
            Thread t=new Thread(r);
            t.start();
            int j=0;
            while(j<=5){
                System.out.println("main主线程");
                try {
                    Thread.sleep(1000);
                    j++;
                }catch (InterruptedException e){
                    throw new RuntimeException();
                }
            }
    }
}
// 2.Runnable匿名类
public class ThreadTwo {
    public static void main(String[] args){
            Runnable r=new Runnable(()->{
            public void run(){
            int i=0;
            while(i<=5) {
                System.out.println("hello,Runnable");
                try{
                    Thread.sleep(1000);
                    i++;
                }catch(InterruptedException e){
                    throw new RuntimeException();
                }
            }
                
        });
            Thread t=new Thread(r);
            t.start();
            int j=0;
            while(j<=5){
                System.out.println("main主线程");
                try {
                    Thread.sleep(1000);
                    j++;
                }catch (InterruptedException e){
                    throw new RuntimeException();
                }
            }
    }
}
//3.Runnable接口与Lambda表达式
    public class ThreadTwo {
    public static void main(String[] args){
           
            Thread t=new Thread(new Runnable(()->{

            public void run(){
            int i=0;
            while(i<=5) {
                System.out.println("hello,Runnable");
                try{
                    Thread.sleep(1000);
                    i++;
                }catch(InterruptedException e){
                    throw new RuntimeException();
                }
            }
                
            });
            t.start();
            int j=0;
            while(j<=5){
                System.out.println("main主线程");
                try {
                    Thread.sleep(1000);
                    j++;
                }catch (InterruptedException e){
                    throw new RuntimeException();
                }
            }
    }
}
// 4.直接使用Lambda表达式
    public class ThreadTwo {
    public static void main(String[] args){
            Thread t=new Thread(()->{
            int i=0;
            while(i<=5) {
                System.out.println("hello,Runnable");
                try{
                    Thread.sleep(1000);
                    i++;
                }catch(InterruptedException e){
                    throw new RuntimeException();
                }
               }
                  });
            t.start();
            int j=0;
            while(j<=5){
                System.out.println("main主线程");
                try {
                    Thread.sleep(1000);
                    j++;
                }catch (InterruptedException e){
                    throw new RuntimeException();
                }
            }
    }
}
//5.继承Thread类实现run()方法
class A extends Thread{
    public void run(){
        int i=0;
        while(i<=3){
            System.out.println("hello,world!,子线程");
            i++;
            try{
                Thread.sleep(1000);
            }catch (InterruptedException e){
                throw new RuntimeException();
            }
        }
    }
}
public class ThreadOne {
    public static void main(String[] args){
     //Thread a=new A();这两种方式都可以
        A a=new A();
      a.start();//开启线程,但不等于立刻执行,只是进入就绪状态,线程的启动顺序与实际执行的顺序没有必然关联
        int j=0;
        while(j<=3){
            System.out.println("main主线程执行");//抢占式调度
            j++;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

    }
}
//6.实现Callable接口(有返回值),创建线程
class A implement Callable<Integer>{
    public Integer call(){
    //任务  int i=0;
            while(i<=5) {
                System.out.println("hello,Runnable");
                try{
                    Thread.sleep(1000);
                    i++;
                }catch(InterruptedException e){
                    throw new RuntimeException();
                }
    
            }
}
//7.FutureTask实现了Future接口,java并发包下的核心工具,本质是Callable任务的包装类
public class B{
    public static void mian(String[] args){

    FutureTask<Integer> task=new FutureTask<>(new A);
    Thread t=new Thread(task);
    t.start();

}
}
//7.线程池创建,submit()可以被execute替换
    public class A{
    public static void main(String[]){
    ExecutorService pool=Executors.newFixedThreadPool(3);//创建三个线程的线程池
    pool.submit(()->{
    //任务,无返回值型
        System.out.print(200);
    });
    //有返回值型
  Future m= pool.execute(()->{
        System.out.print("hello");
        return 200;
    });
    int b=m.get();
}

}

以上方法便是线程的创建。

 2.线程启动

         线程的启动使用使用start()方法(使用它只是把线程启动,而任务的处理取决于CPU的调度),start()是Thread的专属方法,若使用线程池,则内部会自动创建与启动线程。

3.线程中断

          线程的中断是线程间的协作机制,不会强制终止线程,而是给线程发送中断信号,由线程自行决定后续的处理。【注意线程中断与异常终止不同的,异常终止时线程在执行过程中遇到未捕获的异常,jvm会直接终止线程,属于被动强制终止】。线程终止核心:让线程的入口方法能够快点结束,会用到interrupt()【发中断信号,设标志】isInterrupt()【查看中断状态,读取中断标志,返回boolean】、interrupted()【静态方法,查看线程是否被中断并返回boolean值,线程被中断,返回true,并修改中断标记为false,若未中断,返回false】,使用方式之一如下:

public class A{
    public static void main(String[] args){
        Thread t1=new Thread(()->{
            while(!Thread.currentThread().isInterrupted())//真正的中断线程是靠此处的判断
            {
                System.out.println("程序运行中");
            }
            try{
                Thread.sleep(1000);
            }catch(InteruptedException e){
                Thread.currentThread.interupt();
                System.out.println("将jvm因中断才进入的catch中,偷偷修改标志位为false,后使用 Thread.currentThread.interupt()设回原来的标志位")
            }
        });
        T1.start();
        Thread.sleep(3000);
        t1.interrupt();
}
}

线程执行到sleep/wait/join方法触发异常进入catch。【一般我们创建的线程是前台进程,就算主线程结束,只要前台线程没有结束,程序就没有结束,可以用setDaemon()设为后台线程,只要前台线程执行完,后台不管结没结束,都会被强行终止,程序退出】。

 4.线程等待

         线程等待,指一个线程主动等待另一个线程执行完,再继续执行自己的,这里涉及到的方法是1.join()2.join(等待毫秒数) 3.join(等待毫秒,等待纳秒),如图:

public class A{
    public static void main(String[] args){
        Thread t1=new Thread(()->{
            System.out.println("你真帅!");

    });
        t1.start();
        t1.join();
        System.out.println("我的头发是真发!");
    }
}

  5.线程休眠

        线程休眠就是让线程暂停一段时间,主要方法:1.sleep(休眠时间)、2.wait()【wait(内可含等待时间,也可不含)】sleep()静态方法,可强制指定休眠时间,可被中断,不释放锁,时间到,自然唤醒。wait()休眠加释放锁,必须在synchronized块内使用,谁调用它,当前线程释放锁,让其它线程执行,唤醒方式:1.定时 2.notify ()/notifyAll ()唤醒,不过notifyAll()是唤醒所有等待的线程。如图:

 public static void main(String[] args){
        Object o1=new Object();
        Thread t1=new Thread(()->{
            try {
                System.out.println("t1 wait 前");
               synchronized (o1){
                   o1.wait();
                }
                System.out.println("t1 wait之后");
            } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
        });
        Thread t2=new Thread(()->{
            try {
                System.out.println("t2 wait 前");
                synchronized (o1){
                    o1.wait(10000);
                }
                System.out.println("t2 wait之后");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
        Thread t3=new Thread(()->{
                Scanner s=new Scanner(System.in);
                System.out.println("输入任意内容,唤醒线程:");
               int n= s.nextInt();
                synchronized (o1){
                    o1.notify();
                }
        });
        t1.start();
        t2.start();
        t3.start();
    }
}

6.获取线程实例

        除了直接创建获取线程实例,还可以使用Thread.currentThread();获取当前线程,此处就不过多演示了。

7.获取与设置线程属性的方法

        获取线程属性的常用方法:1.getName()获取线程名字、2.getId()获取线程唯一ID、3.isAlive()判断线程是否存活、4.getState()获取线程状态【new(新建)、RUNNABLE(就绪/运行状态,调用start后进入)、BLOCKED(阻塞状态,就只有锁阻塞,被动等锁)、WAITING(无限等待状态)、TIMED_WAITING(限时等待状态)、TERMINATED(终止状态)】。设置线程属性的常用方法:setName()设置线程名称、setPriority()设置线程的优先级,CPU倾向调度,但不保证执行。

        完结,撒花~~~(若有误,望告知,感谢!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐