zoukankan      html  css  js  c++  java
  • java 多线程一、


    * 什么是线程
    * 线程是程序执行的一条路径, 一个进程中可以包含多条线程
    * 多线程并发执行可以提高程序的效率, 可以同时完成多项工作

    多线程并行和并发的区别
    * 并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在进行。(需要多核CPU)
    * 并发是指两个任务都请求运行,而处理器只能按受一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。
    * 比如我跟两个网友聊天,左手操作一个电脑跟甲聊,同时右手用另一台电脑跟乙聊天,这就叫并行。
    * 如果用一台电脑我先给甲发个消息,然后立刻再给乙发消息,然后再跟甲聊,再跟乙聊。这就叫并发。

    多线程(Java程序运行原理和JVM的启动是多线程的吗)
    * A:Java程序运行原理
    * Java命令会启动java虚拟机,启动JVM,等于启动了一个应用程序,也就是启动了一个进程。该进程会自动启动一个 “主线程” ,然后主线程去调用某个类的 main 方法。
    
    * B:JVM的启动是多线程的吗
    * JVM启动至少启动了垃圾回收线程和主线程,所以是多线程的。
    
    ###多线程(多线程程序实现的方式1)
    * 1.继承Thread
    * 定义类继承Thread
    * 重写run方法
    * 把新线程要做的事写在run方法中
    * 创建线程对象
    * 开启新线程, 内部会自动执行run方法
    * 
    
    public class Demo2_Thread {
    
    /**
    * @param args
    */
    public static void main(String[] args) {
    MyThread mt = new MyThread();    //4,创建自定义类的对象
    mt.start();    //5,开启线程
    
    for(int i = 0; i < 3000; i++) {
    System.out.println("bb");
    }
    }
    
    }
    class MyThread extends Thread {    //1,定义类继承Thread
    public void run() {    //2,重写run方法
    for(int i = 0; i < 3000; i++) {    //3,将要执行的代码,写在run方法中
    System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
    }
    }
    }
    多线程程序实现的方式2
    * 2.实现Runnable
        * 定义类实现Runnable接口
        * 实现run方法
        * 把新线程要做的事写在run方法中
        * 创建自定义的Runnable的子类对象
        * 创建Thread对象, 传入Runnable
        * 调用start()开启新线程, 内部会自动调用Runnable的run()方法
    
                public class Demo3_Runnable {
                    /**
                     * @param args
                     */
                    public static void main(String[] args) {
                        MyRunnable mr = new MyRunnable();                        //4,创建自定义类对象
                        //Runnable target = new MyRunnable();
                        Thread t = new Thread(mr);                                //5,将其当作参数传递给Thread的构造函数
                        t.start();                                                //6,开启线程
                        
                        for(int i = 0; i < 3000; i++) {
                            System.out.println("bb");
                        }
                    }
                }
                
                class MyRunnable implements Runnable {                            //1,自定义类实现Runnable接口
                    @Override
                    public void run() {                                            //2,重写run方法
                        for(int i = 0; i < 3000; i++) {                            //3,将要执行的代码,写在run方法中
                            System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
                        }
                    }
                    
                }

    实现Runnable的原理
    * 查看源码
    * 1,看Thread类的构造函数,传递了Runnable接口的引用
    * 2,通过init()方法找到传递的target给成员变量的target赋值
    * 3,查看run方法,发现run方法中有判断,如果target不为null就会调用Runnable接口子类对象的run方法

    ###两种方式的区别
    * 查看源码的区别

    * a.继承Thread : 由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法
    * b.实现Runnable : 构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable的引用是否为空, 不为空编译时看的是Runnable的run(),运行时执行的是子类的run()方法

    ==========================================================================

    * 继承Thread
    * 好处是:可以直接使用Thread类中的方法,代码简单
    * 弊端是:如果已经有了父类,就不能用这种方法
    * 实现Runnable接口
    * 好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的
    * 弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂

    =========================================================================

    多线程(匿名内部类实现线程的两种方式)
    * 继承Thread类


    第一种:
    new Thread() { //1,new 类(){}继承这个类
    public void run() { //2,重写run方法
    for(int i = 0; i < 3000; i++) { //3,将要执行的代码,写在run方法中
    System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaa");
    }
    }
    }.start();
    * 实现Runnable接口

    第二种:
    new Thread(new Runnable(){ //1,new 接口(){}实现这个接口
    public void run() { //2,重写run方法
    for(int i = 0; i < 3000; i++) { //3,将要执行的代码,写在run方法中
    System.out.println("bb");
    }
    }
    }).start();

    ===================================================

    获取名字第一种方式:

    多线程(获取名字和设置名字)
    * 1.获取名字
        * 通过getName()方法获取线程对象的名字
    * 2.设置名字
        * 通过构造函数可以传入String类型的名字
        * 
                new Thread("xxx") {
                    public void run() {
                        for(int i = 0; i < 1000; i++) {
                            System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa");
                        }
                    }
                }.start();
                
                new Thread("yyy") {
                    public void run() {
                        for(int i = 0; i < 1000; i++) {
                            System.out.println(this.getName() + "....bb");
                        }
                    }
                }.start(); 
        * 通过setName(String)方法可以设置线程对象的名字
        * 
                Thread t1 = new Thread() {
                    public void run() {
                        for(int i = 0; i < 1000; i++) {
                            System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa");
                        }
                    }
                };
                
                Thread t2 = new Thread() {
                    public void run() {
                        for(int i = 0; i < 1000; i++) {
                            System.out.println(this.getName() + "....bb");
                        }
                    }
                };
                t1.setName("芙蓉姐姐");
                t2.setName("凤姐");
                
                t1.start();
                t2.start();

    获取名称第二种方式:

    * Thread.currentThread(), 主线程也可以获取
        * 
                new Thread(new Runnable() {
                    public void run() {
                        for(int i = 0; i < 1000; i++) {
                            System.out.println(Thread.currentThread().getName() + "...aaaaaaaaaaaaaaaaaaaaa");
                        }
                    }
                }).start();
                
                new Thread(new Runnable() {
                    public void run() {
                        for(int i = 0; i < 1000; i++) {
                            System.out.println(Thread.currentThread().getName() + "...bb");
                        }
                    }
                }).start();
                Thread.currentThread().setName("我是主线程");                    //获取主函数线程的引用,并改名字
                System.out.println(Thread.currentThread().getName());        //获取主函数线程的引用,并获取名字
                Thread.currentThread().setName("我是主线程");                    //获取主函数线程 main() 的引用,并改名字
                System.out.println(Thread.currentThread().getName());        //获取主函数线程的引用,并获取名字







    =====================================================================================
    休眠线程
    休眠线程
    * Thread.sleep(毫秒,纳秒), 控制当前线程休眠若干毫秒1秒= 1000毫秒 1秒 = 1000 * 1000 * 1000纳秒 1000000000
    
                new Thread() {
                    public void run() {
                        for(int i = 0; i < 10; i++) {
                            System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
                            try {
                                Thread.sleep(10);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();
                
                new Thread() {
                    public void run() {
                        for(int i = 0; i < 10; i++) {
                            System.out.println(getName() + "...bb");
                            try {
                                Thread.sleep(10);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start();

    守护线程
    * setDaemon(), 设置一个线程为守护线程, 该线程不会单独执行, 当其他非守护线程都执行结束后, 自动退出

    * 
    Thread t1 = new Thread() {
    public void run() {
    for(int i = 0; i < 50; i++) {
    System.out.println(getName() + "...aaaaaaaaaaaaaaaaaaaaaa");
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    };
    
    Thread t2 = new Thread() {
    public void run() {
    for(int i = 0; i < 5; i++) {
    System.out.println(getName() + "...bb");
    try {
    Thread.sleep(10);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    };
    
    t1.setDaemon(true);    //将t1设置为守护线程
    
    t1.start();
    t2.start();
  • 相关阅读:
    VIJOS-P1340 拯救ice-cream(广搜+优先级队列)
    uva 11754 Code Feat
    uva11426 GCD Extreme(II)
    uvalive 4119 Always an Interger
    POJ 1442 Black Box 优先队列
    2014上海网络赛 HDU 5053 the Sum of Cube
    uvalive 4795 Paperweight
    uvalive 4589 Asteroids
    uvalive 4973 Ardenia
    DP——数字游戏
  • 原文地址:https://www.cnblogs.com/yimian/p/6562268.html
Copyright © 2011-2022 走看看