day24 Java学习 多线程

多线程(多线程的引入)

      线程 :

            * 线程是程序执行的一条路径,一个进程中可以包含多条线程。

            * 多线程并发执行可以提高程序的效率,可以同时完成多项工作。

      应用场景:

            * 服务器同时处理多个客户端请求。

多线程(多线程并行和并发的区别) 

            * 并行就是两个任务同时运行,就是甲任务进行的同时,乙任务也在运行。( 需要多个cpu)

            * 并发是指两个任务都请求运行,而处理器只能接收一个任务,就把这两个任务安排轮流进行,由于时间间隔较短,使人感觉两个任务都在运行。

多线程(多线程程序实现的方式 ) 

    * extends Thread:

public class Dome1_Thread {

public static void main(String[] args) {
        // 
         MyThread my=new MyThread();       //4.创建MyThread子类对象
         my.start();                       //5.statr()开启线程
         for (int i = 0; i <10; i++) {
            System.out.println("b");
            
        }
    }

}
 
 class MyThread extends Thread{     //1.继承Thread
     public void run() {            //2.重写run()
        for (int i = 0; i < 10; i++) {   //3.将要执行的代码放在run()中 
            System.out.println("aaa");
            
        }
        for (int i = 0; i < 10; i++) {   //将要执行的代码放在run()中 
            System.out.println("ccc");
            
        }
    }
 }
例子

    *  implements Runnable:

public class Dome1_Thread {

    public static void main(String[] args) {
        //
        MyRunnable mr = new MyRunnable();  //4.创建Runnable的子类对象
        Thread t = new Thread(mr);         //5.将其当作参数传递给Thread的构造函数
        t.start();                         //6.开启线程
        for (int i = 0; i < 10; i++) {
            System.out.println("b");

        }
    }


}
 class MyRunnable implements Runnable{      //1.定义一个类实现Runnable

    @Override
    public void run() {                     //2.重写run()
        for (int i = 0; i < 10; i++) {      //3.将要执行的代码放在run()中 
            System.out.println("aaa");
            
        }    
    }      
 }
例子

两种方式的区别:

    * 继承Thread 

                * 好处是:可以直接使用Thread类中的方法,代码简单。

                * 弊端是:如果已经有了父类,就不能用这种方法。

     * 实现Runnable接口:

                * 好处是:即使自己定义的线程类有了父类也没关系,因为父类也可以实现接口,而且接口是可以多实现的。

                * 弊端是:不能直接使用Thread中的方法需要先获取线程对象后才能得到Thread的方法。

多线程(匿名内部类实现线程)

  

public static void main(String[] args) {
        //方法1:
        new Thread() {                              // 1.继承Thread()
            public void run() {                     // 2.重写run()
                for (int i = 0; i <= 10; i++) {     // 3.将要执行的代码放在run()中
                    System.out.println("aaa");
                }
            }
        }.start();                                   // 4.statr()开启线程
        
        //方法2:
        new Thread( new Runnable() {              //1.将Runnable的子类对象传递给Thread的构造方法
            public void run() {                   // 2.重写run()
                for (int i = 0; i <= 10; i++) {   // 3.将要执行的代码放在run()中
                    System.out.println("bbb");
                }
            } 
        }).start();                               // 4.statr()开启线程
    }
例子

多线程(获取当前线程的对象)

  * Thread.currentThread() :获取当前正在执行的线程。

public static void main(String[] args) {
        new Thread() {                              
            public void run() {    
                System.out.println(this.getName() + "...aaa"); 
            }
        }.start();

        new Thread( new Runnable() {              
            public void run() {                 
                //Thread.currentThread()获取当前正在执行的线程
                    System.out.println(Thread.currentThread().getName() +"...bbb");        
            } 
        }).start();    
        // 设置主线程名字
        Thread.currentThread().setName("陈琳狗");
        //获取主线程名字
        System.out.println(Thread.currentThread().getName());

    }
例子

多线程(休眠线程)

  * Thread.sleep(毫秒 ,纳秒):控制当前线程休眠若干毫秒

   (1秒=1000 毫秒      1秒=1000*1000*1000 纳秒)

多线程(守护线程)

  *  setDaemon( ) :设置一个线程为守护线程,该线程不会单独执行,当其他非守护线程都执行结束后,自动推出。( 当传入为true就是意味着设置为守护线程。)

多线程(加入线程)

  *  join( ) :当前线程暂停,等待指定的线程执行结束后,当前线程再继续。

 *  join( int ) :可以等待指定的毫秒之后继续。

public static void main(String[] args) {
    final    Thread t1 = new Thread() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    System.out.println(getName() + "....aaa");
                }
            }
        };
        
        Thread t2 = new Thread() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    if (i==2) {
                        try {
//                            t1.join();
                            t1.join(1); // 插队指定时间,过了指定时间后,两条线程交替执行
                        } catch (InterruptedException e) {
                            // TODO 自动生成的 catch 块
                            e.printStackTrace();
                        }
                    }
                    System.out.println(getName() + "....bbbbbb");
                }
            }
        };
    t1.start();
    t2.start();
    
    }
例子

多线程(设置线程的优先级)

setPriority (Thread .MIN_PRIORITY);

setPriority (Thread .MAX_PRIORITY);

多线程(同步代码块)

synchronized( ){  } :同步代码块,锁机制,锁对象可以是任意的(锁对象不能用匿名对象,因为匿名对象不是同一个对象)。

使用情况:

                 * 当多线程并发,有多段代码同时执行时,我们希望某一段代码执行的过程中CPU不要切换到其他线程工作,这时就需要同步。

                 * 如果两段代码块是同步的,那么同一时间只能执行一段,在一段代码块没执行结束之前,不会执行另外一段代码。

同步代码块:多个同步代码如果使用相同的锁对象,那么他们就是同步的。

public class Dome1_Synchronized {

    public static void main(String[] args) {
        final printss p = new printss();
        new Thread() {
            public void run() {
                while (true) {
                    p.print1();
                }
            }
        }.start();

        new Thread() {
            public void run() {
                while (true) {
                    p.print2();
                }
            }
        }.start();

    }

}

class printss {
    Dome d=new Dome();
    public void print1() {
          synchronized (d) {        //synchronized(){} :同步代码块,锁机制,锁对象可以是任意的(锁对象不能用匿名对象,因为匿名对象不是同一个对象)
            System.out.print("a");
        System.out.print("b");
        System.out.print("c");
        System.out.println("
");
        }
            
        
        
    }
    
    public void print2() {
        synchronized (d) {
            System.out.print("e");
            System.out.print("f");
            System.out.print("g");
            System.out.println("
");
        }

    }
}

class Dome{
    
}
例子

多线程(同步方法)

同步方法只需要在方法上加synchronized关键字即可。

public synchronized void print1() {   //同步方法只需要在方法上加synchronized关键字即可。
          System.out.print("a");
            System.out.print("b");
            System.out.print("c");
            System.out.println("
");
    }
    
    public void print2() {                //非静态的同步方法的锁对象是this
        synchronized (this) {                     
            System.out.print("d");
        System.out.print("e");
        System.out.print("f");
        System.out.println("
");
        }
        
    }
    
    
非静态的同步方法
//静态同步方法
class printstatic{
    public  synchronized void print1() {   //同步方法只需要在方法上加synchronized关键字即可。
          System.out.print("a");
            System.out.print("b");
            System.out.print("c");
            System.out.println("
");
    }
    
    public void print2() {               
        synchronized (printstatic.class) {  //静态的同步方法的锁对象是该类的字节码对象
            System.out.print("d");
        System.out.print("e");
        System.out.print("f");
        System.out.println("
");
        }        
    }
}
静态的同步方法

多线程(线程安全问题)

   * 多线程并发操作同一数据时,就有可能出现线程安全问题。

   * 使用同步技术可以解决这种问题,把操作数据的代码进行同步,不要多个线程一起操作。

public class Dome3_Ticket {

    public static void main(String[] args) {
        //需求:卖100张票,四个窗口
        new Ticket().start();
        new Ticket().start();
        new Ticket().start();
        new Ticket().start();
    }

}

class Ticket extends Thread{
        private static int ticket=100;      //增加Static静态使四个线程公用一个ticket
//        private static Object object=new Object();   //如果用引用数据类型成员变量当作锁对象,必须是静态的。 
        public void   run() {
            while (true) {
                synchronized (Ticket.class) {
                    if (ticket<=0) {
                    break;
                }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        // TODO 自动生成的 catch 块
                        e.printStackTrace();
                    }
                System.out.println(getName()+"...这是第"+ticket--+"号票");
                }
                
            }
            
        }

}
例子
public class Dome_Ticket {

    public static void main(String[] args) {
        // Runnable接口实现火车站卖票例子 4个窗口
            MyTicket mt= new MyTicket();
            new Thread(mt).start();
            new Thread(mt).start();
            new Thread(mt).start();
            new Thread(mt).start();
    }

}

class MyTicket implements Runnable{
        private int ticket=100;
    @Override
    public void run() {
        while (true) {
            synchronized (Ticket.class) {
                if (ticket<=0) {
                break;
            }
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    // TODO 自动生成的 catch 块
                    e.printStackTrace();
                }
            System.out.println(Thread.currentThread().getName()+"...这是第"+ticket--+"号票");
            }    
        }
        
    }
    
}
Runnable接口实现

多线程(死锁)

    多线程同步的时候,如果同步代码块嵌套,使用相同的锁,就有可能出现死锁。(尽量不要嵌套使用) 

原文地址:https://www.cnblogs.com/feng0001/p/10977260.html