Java线程

java多线程学习


一、什么是线程?什么是进程?两者又有什么区别?

这里写图片描述

二、线程的状态有哪些?

这里写图片描述


三、线程的实现

这里写图片描述

注意,当用start()实现多线程的时候,线程会实现并发执行,也就是那个线程抢到了cpu那个就执行。如果用run()方法,那就是线程1执行完之后才会只能线程2,就不会有并发。

3.1,使用继承Thread方法,实现三个线程并发

  • 代码线程工具类实现
public class ThreadUtil extends Thread {

        public String names;

        public ThreadUtil(String name) {
            super();
            names = name;
        }
        //写一个构造方法,来接通主类

        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                System.out.println(names+" :次数 "+i);
            }
        }
}
  • 引用类
public class MyThread {
    public static void main(String[] args) {

        ThreadUtil tu1 = new ThreadUtil("我是线程tu1");
        ThreadUtil tu2 = new ThreadUtil("我是线程tu2");
        ThreadUtil tu3 = new ThreadUtil("我是线程tu3");
        tu1.start();
        tu2.start();
        tu3.start();
    }
}
  • 打印结果:
    这里写图片描述

3.2,使用Runnable接口

  • Runnable工具类

public class MyRunnable implements Runnable{

    public String names;

    public MyRunnable(String name) {
        super();
        names = name;
    }
    //写一个构造方法,来接通主类

    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(names+" :次数 "+i);
        }
    }
}

-主类引用


public class MyThread {
    public static void main(String[] args) {

        MyRunnable tu1 = new MyRunnable("我是实现Runnable的线程tu1");
        MyRunnable tu2 = new MyRunnable("我是实现Runnable线程tu2");
        MyRunnable tu3 = new MyRunnable("我是实现Runnable线程tu3");
        //切记这里不能直接,tu1.start()。你需要创建一个Thread对象来接受我们实现的线程对象

        Thread tr1 = new Thread(tu1);
        tr1.start();

        Thread tr2 = new Thread(tu2);
        tr2.start();

        Thread tr3 = new Thread(tu3);
        tr3.start();
    }

}
  • 运行结果:成功:
    这里写图片描述

四、线程的常用方法

这里写图片描述

4.1代码来验证这些方法

  • 代码模块:
public class TextRunnable{

    public static void main(String[] args) {
        TextRunnables trR = new TextRunnables("线程名称");
        Thread td1 = new Thread(trR);
        //来验证是否启动状态
        System.out.println("线程的状态1:"+td1.isAlive());
        td1.start();
        System.out.println("线程的状态2:"+td1.isAlive());


        //下面代码含义在于测试线程的join()强制执行的方法    
        for (int i = 0; i < 20; i++) {
            //在主线程写一个循环,执行20次,然后当主线程执行到10的时候,强制执行子线程。如下
            if (i==10) {
                try {
                    td1.join();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println("主线程:"+i);
        }
    }


    static class TextRunnables implements Runnable{

            public String names;


            public TextRunnables(String name) {
                names = name;
            }
            //写一个构造方法,来接通主类

            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    //获取线程的名称
                    System.out.println("线程名称: "+Thread.currentThread().getName());
                }
            }

     }

}
  • 1、获取线程的名称
`System.out.println("线程名称: "+Thread.currentThread().getName());
  • 2、判断线程是否启动
TextRunnables trR = new TextRunnables("线程名称");
        Thread td1 = new Thread(trR);
        //来验证是否启动状态
        System.out.println("线程的状态1:"+td1.isAlive());//打印是未启动
        td1.start();
        System.out.println("线程的状态2:"+td1.isAlive());//打印已经未启动
  • 3、验证强制开启子线程join()方法
//下面代码含义在于测试线程的join()强制执行的方法    
        for (int i = 0; i < 20; i++) {
            //在主线程写一个循环,执行20次,然后当主线程执行到10的时候,强制执行子线程。如下
            if (i==10) {
                try {
                    td1.join();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            System.out.println("主线程:"+i);
        }
    }
  • 剩下的还有睡眠sleep(),还有一个礼让方法yieid()方法,这里就不说了。
  • -

四、线程的优先级

这里写图片描述

代码模块



public class MyRunnable02 {
     public static void main(String[] args) {
         //然后我们创建三个线程。来引用线程的优先级
         Thread t1 = new Thread(new TextRunnables(),"A");
         Thread t2 = new Thread(new TextRunnables(),"B");
         Thread t3 = new Thread(new TextRunnables(),"C");
         //设置优先级
         t1.setPriority(Thread.MAX_PRIORITY);
         t2.setPriority(Thread.MIN_PRIORITY);
         t3.setPriority(Thread.NORM_PRIORITY);
         //开启线程
         t1.start();
         t2.start();
         t3.start();

        }


        static class TextRunnables implements Runnable{

                //写一个构造方法,来接通主类

                @Override
                public void run() {
                    for (int i = 0; i < 5; i++) {
                        //获取线程的名称
                        try {
                            Thread.sleep(1000);
                            System.out.println("线程名称: "+Thread.currentThread().getName()+i);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    }
                }

         }

    }

结果分析:优先级高,提高的是占CPU的效率,而非就一定谁的高就必须先执行


  • 这里写图片描述

五、线程的同步

这里写图片描述

5.1:什么时候需要用到同步呢? 就是程序的资源需要给多个线程共享的时候,打个比方,火车站有5张车票 ,三个人去抢。如果没有任何管理的情况下,就会出现有人付过钱了但是没有获得票的结局。例如下方代码


public class MyRunnable02 {
     public static void main(String[] args) {
         //然后我们创建三个线程。来引用线程的优先级
         TextRunnables fRunnables = new TextRunnables();

         Thread t1 = new Thread(fRunnables);
         Thread t2 = new Thread(fRunnables);
         Thread t3 = new Thread(fRunnables);
         //开启线程
         t1.start();
         t2.start();
         t3.start();

        }


        static class TextRunnables implements Runnable{
                //假设有五张牌
                private int ticket = 5;
                @Override
                public void run() {

                        for (int i = 0; i < 10; i++) {
                            //如果还有票就继续抢
                            if(ticket>0){
                            //获取线程的名称
                            try {
                                //睡眠500毫秒抢一次
                                Thread.sleep(500);  
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            //如果被抢走,就减少一张票数量
                            System.out.println("车票剩余: "+ticket--);
                        }

                    }

                }
         }
    }

运行结果

这里写图片描述

5.2:所以我们就要用到同步(synchronized)来分配资源,这样就好比有一个专门的售票员一样,一手交钱一手交货, 相比5.1中,也就是在处理车票数据的时候添加一个同步锁



public class MyRunnable02 {
     public static void main(String[] args) {
         //然后我们创建三个线程。来引用线程的优先级
         TextRunnables fRunnables = new TextRunnables();

         Thread t1 = new Thread(fRunnables);
         Thread t2 = new Thread(fRunnables);
         Thread t3 = new Thread(fRunnables);
         //开启线程
         t1.start();
         t2.start();
         t3.start();

        }


        static class TextRunnables implements Runnable{
                //假设有五张牌
                private int ticket = 5;
                @Override
                public void run() {
                    //加一个同步代码块,这样就可以合理的分配资源,不会出现cpu抢占资源问题
                    synchronized (this) {
                        for (int i = 0; i < 10; i++) {
                            //如果还有票就继续抢
                            if(ticket>0){
                            //获取线程的名称
                            try {
                                //睡眠500毫秒抢一次
                                Thread.sleep(500);  
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                            //如果被抢走,就减少一张票数量
                            System.out.println("车票剩余: "+ticket--);
                        }

                    }
                    }



                }
         }
    }

运行结果

这里写图片描述


5.3:我们上面5.2用的是同步代码块,那我们用同步方法如何实现的,其实很简单,只需要声明一个同步的方法即可。如下:

public class MyRunnable02 {
     public static void main(String[] args) {
         //然后我们创建三个线程。来引用线程的优先级
         TextRunnables fRunnables = new TextRunnables();

         Thread t1 = new Thread(fRunnables);
         Thread t2 = new Thread(fRunnables);
         Thread t3 = new Thread(fRunnables);
         //开启线程
         t1.start();
         t2.start();
         t3.start();
        }

        static class TextRunnables implements Runnable{
                //假设有五张牌
                private int ticket = 5;
                @Override
                public void run() {
                    //直接调用同步方法即可
                     tell();
                }

                //写一个同步的方法
                public synchronized void tell(){
                    for (int i = 0; i < 10; i++) {
                        //如果还有票就继续抢
                        if(ticket>0){
                        //获取线程的名称
                        try {
                            //睡眠500毫秒抢一次
                            Thread.sleep(500);  
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        //如果被抢走,就减少一张票数量
                        System.out.println("车票剩余: "+ticket--);
                    }
                }
                }
         }
    }

运行结果:也是正确的运行,只是处理同步资源的时候,放在一个同步方法中去处理

这里写图片描述


六、什么是死锁?

打个比方,一对情侣,女方必须要求南方在北京买一套3000万的房子,男子缺必须在老家买个30万的别墅。两个人就开始相互争执,这就造成了问题的无法解决,就可以理解为死锁。解决的办法,就是双方的某一方,降低自己的要求,能使两者都接受就可以了。

七、线程的生命周期?

这里写图片描述

就那么多把。都是最基础的。想深入了解的小伙伴可以i多搜搜这方面的知识!特别是线程同步多多注意

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值