记录JAVA多线程学习

1.实现方式:
多线程的实现方式有两种方式,一种是继承Thread类,一种是实现runnable接口。
继承thread类:

package com.heima.thread;

public class Demo2_Thread {

    /**
     * @param args
     */
    public static void main(String[] args) {
        MyThread mt = new MyThread();       //4,创建Thread类的子类对象
        mt.start();                         //5,开启线程
        
        for(int i = 0; i < 1000; i++) {
            System.out.println("bb");
        }
    }

}

class MyThread extends Thread {             //1,继承Thread
    public void run() {                     //2,重写run方法
        for(int i = 0; i < 1000; i++) {     //3,将要执行的代码写在run方法中
            System.out.println("aaaaaaaaaaaa");
        }
    }
}

接口方式:

package com.heima.thread;

public class Demo3_Thread {

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

}

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

    @Override
    public void run() {                     //2,重写run方法
        for(int i = 0; i < 1000; i++) {     //3,将要执行的代码写在run方法中
            System.out.println("aaaaaaaaaaaa");
        }
    }
    
}

2.休眠线程(sleep)
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();

3.守护线程(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();

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

  • join(int), 可以等待指定的毫秒之后继续
            final 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 < 50; i++) {
                        if(i == 2) {
                            try {
                                //t1.join();                        //插队,加入
                                t1.join(30);                        //加入,有固定的时间,过了固定时间,继续交替执行
                                Thread.sleep(10);
                            } catch (InterruptedException e) {
                                
                                e.printStackTrace();
                            }
                        }
                        System.out.println(getName() + "...bb");
                    
                    }
                }
            };
            
            t1.start();
            t2.start();

5.礼让线程

  • yield让出cpu

6.设置线程的优先级

  • setPriority()设置线程的优先级

7.同步代码块

  • 1.什么情况下需要同步
    • 当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
    • 如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
  • 2.同步代码块
    • 使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
    • 多个同步代码块如果使用相同的锁对象, 那么他们就是同步的
            class Printer {
                Demo d = new Demo();
                public static void print1() {
                    synchronized(d){                //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
                    
                        System.out.print("程");
                        System.out.print("序");
                        System.out.print("员");
                        System.out.print("\r\n");
                    }
                }
    
                public static void print2() {   
                    synchronized(d){    
                        System.out.print("1");
                        System.out.print("2");
                        System.out.print("3");
                        System.out.print("4");
                        System.out.print("\r\n");
                    }
                }
            }

8.同步方法

  • 使用synchronized关键字修饰一个方法, 该方法中所有的代码都是同步的
        class Printer {
            public static void print1() { 
                synchronized(Printer.class){                //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
                    
                    System.out.print("程");
                    System.out.print("序");
                    System.out.print("员");
                    System.out.print("\r\n");
                }
            }
            /*
             * 非静态同步函数的锁是:this
             * 静态的同步函数的锁是:字节码对象
             */
            public static synchronized void print2() {  
                System.out.print("1");
                System.out.print("2");
                System.out.print("3");
                System.out.print("4");
                System.out.print("\r\n");
            }
        }

9.线程安全问题

  • 多线程并发操作同一数据时, 就有可能出现线程安全问题
  • 使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起操作
            public class Demo2_Synchronized {

                /**
                 * @param args
                 * 需求:铁路售票,一共100张,通过四个窗口卖完.
                 */
                public static void main(String[] args) {
                    TicketsSeller t1 = new TicketsSeller();
                    TicketsSeller t2 = new TicketsSeller();
                    TicketsSeller t3 = new TicketsSeller();
                    TicketsSeller t4 = new TicketsSeller();
                    
                    t1.setName("窗口1");
                    t2.setName("窗口2");
                    t3.setName("窗口3");
                    t4.setName("窗口4");
                    t1.start();
                    t2.start();
                    t3.start();
                    t4.start();
                }
            
            }
            
            class TicketsSeller extends Thread {
                private static int tickets = 100;
                static Object obj = new Object();
                public TicketsSeller() {
                    super();
                    
                }
                public TicketsSeller(String name) {
                    super(name);
                }
                public void run() {
                    while(true) {
                        synchronized(obj) {
                            if(tickets <= 0) 
                                break;
                            try {
                                Thread.sleep(10);//线程1睡,线程2睡,线程3睡,线程4睡
                            } catch (InterruptedException e) {
                                
                                e.printStackTrace();
                            }
                            System.out.println(getName() + "...这是第" + tickets-- + "号票");
                        }
                    }
                }
            }

10.两个线程间的通信

  • 1.什么时候需要通信
    • 多个线程并发执行时, 在默认情况下CPU是随机切换线程的
    • 如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印
  • 2.怎么通信
    • 如果希望线程等待, 就调用wait()
    • 如果希望唤醒等待的线程, 就调用notify();
    • 这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用

public class TestTwoThread {
    
    public static void main(String[] args) {
        printer p = new printer();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
            }
        }.start();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
            }
        }.start();
        
    }

}

class printer {
    int flag = 1;
    
    public void print1() throws InterruptedException {
        
        synchronized (this) {
            while(flag!=1) {
                this.wait();
            }
                System.out.print("a");
                System.out.print("b");
                System.out.print("c");
                System.out.println();
                flag=2;
                this.notify();    //随机唤醒当前wait状态的线程
            
            
        }
        
            
        
        
    }
    
    public void print2() throws InterruptedException {
        
        synchronized (this) {
            while(flag!=2) {
                this.wait();
            }
            System.out.print("1");
            System.out.print("2");
            System.out.print("3");
            System.out.println();
            flag=1;
            this.notify();
        }
            
        
        
    }
    
}

11.用ReentrantLock和Codintion方式去实现两个进程的通讯

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class TestTwoThread2 {
    
    public static void main(String[] args) {
        printer2 p = new printer2();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print1();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
            }
        }.start();
        
        new Thread() {
            public void run() {
                while(true) {
                    try {
                        p.print2();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
            }
        }.start();
        
    }

}

class printer2 {
    int flag = 1;
    private ReentrantLock r = new ReentrantLock();
    private Condition c1 = r.newCondition();
    private Condition c2 = r.newCondition();
    public void print1() throws InterruptedException {
        
        r.lock();
        if(flag!=1) {
            c1.await();
        }
        System.out.print("a");
        System.out.print("b");
        System.out.print("c");
        System.out.println();
        flag=2;
        c2.signal();    
        r.unlock();
            
    }
    
    public void print2() throws InterruptedException {
        
        r.lock();
        if(flag!=2) {
            c2.await();
        }
        System.out.print("1");
        System.out.print("2");
        System.out.print("3");
        System.out.println();
        flag=1;
        c1.signal();
        r.unlock(); 
        
        
    }
    
}

你可能感兴趣的:(记录JAVA多线程学习)