美文网首页
记录JAVA线程学习

记录JAVA线程学习

作者: ccccaixiaohao | 来源:发表于2019-07-15 21:10 被阅读0次

1.JAVA线程的两种方式:

  a.继承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");
        }
    }
}

b.实现Runnable接口:

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");
        }
    }
    
}

c.获取当前线程名称:

public class test {
    
    public static void main(String[] args) {
        
        new Thread() {
            public void run() {
                System.out.println(getName()+"...aaaa");
            }
        }.start();
        
        new Thread(new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getName()+".....bbbbbbbbbbbbb");
                
            }
        }).start();
        
        System.out.println(Thread.currentThread().getName());
    }

}

2.线程的方法

a.获取名字
 通过getName()方法获取线程对象的名字
new Thread("xxx") {
                public void run() {
                    for(int i = 0; i < 1000; i++) {
                        System.out.println(this.getName() + "....aaaaaaaaaaaaaaaaaaaaaaa");
                    }
                }
            }.start();
b.设置名字
 通过构造函数可以传入String类型的名字
Thread t2 = new Thread() {
                public void run() {
                    for(int i = 0; i < 1000; i++) {
                        System.out.println(this.getName() + "....bb");
                    }
                }
            };
            t2.setName("凤姐");
c.获取当前线程
new Thread(new Runnable() {
                public void run() {
                    for(int i = 0; i < 1000; i++) {
                        System.out.println(Thread.currentThread().getName() + "...aaaaaaaaaaaaaaaaaaaaa");
                    }
                }
            }).start();

3.线程分类

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

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

c.加入线程
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();

d.礼让线程
yield()让出cpu

e.设置线程的优先级
setPriority()设置线程的优先级

4.线程的同步

a.什么情况下需要同步
当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
b.同步代码块

class Printer {
                Demo d = new Demo();
                public static void print1() {
                    synchronized(d){                //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
                        System.out.print("a");
                        System.out.print("b");
                        System.out.print("c");
                        System.out.print("d");
                        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");
                    }
                }
            }

c.同步方法

class Printer {
            public static void print1() {
                synchronized(Printer.class){                //锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
                    System.out.print("a");
                    System.out.print("b");
                    System.out.print("c");
                    System.out.print("d");
                    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");
            }
        }

5.两个线程之间的通信

如果希望线程等待, 就调用wait()
如果希望唤醒等待的线程, 就调用notify();
这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用


public class waitNotify {
    
    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{
    private int flag = 1;
    void print1() throws InterruptedException {
            synchronized(this) {
                if(!(flag == 1)) {
                    this.wait();
                }
            System.out.print("a");
            System.out.print("b");
            System.out.print("c");
            System.out.print("d");
            System.out.println();
            flag = 2;
            this.notify();
        }
        
    }
    
    void print2() throws InterruptedException {
                synchronized(this) {
                    if(!(flag == 2)) {
                        this.wait();
                    }
                System.out.print("1");
                System.out.print("2");
                System.out.print("3");
                System.out.print("4");
                System.out.println();
                flag = 1;
                this.notify();
            }
        
    }
}

sleep方法和wait方法的区别
* sleep在同步代码块或者同步函数中,不释放锁
* wait在同步代码块或者同步函数中,释放锁
* sleep方法必须传入参数,参数其实就是时间,时间到了自动醒来
* wait方法可以传入参数,也可以不传入参数
* 如果给wait方法传入时间参数,用法与sleep相似,时间到就停止等待,但其锁对象是释放的

6.新特性的互斥锁

  • 使用ReentrantLock类的newCondition()方法可以获取Condition对象
  • 需要等待的时候使用Condition的await()方法, 唤醒的时候用signal()方法
  • 不同的线程使用不同的Condition, 这样就能区分唤醒的时候找哪个线程了
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class reetrantLock {

    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{
    ReentrantLock r = new ReentrantLock();
    Condition d1 = r.newCondition();
    Condition d2 = r.newCondition();
    private int flag = 1;
    void print1() throws InterruptedException {
            r.lock();
                if(!(flag == 1)) {
                    d1.await();
                }
            System.out.print("a");
            System.out.print("b");
            System.out.print("c");
            System.out.print("d");
            System.out.println();
            flag = 2;
            d2.signal();
            r.unlock();
    
        
    }
    
    void print2() throws InterruptedException {
            r.lock();
                    if(!(flag == 2)) {
                        d2.await();
                    }
                System.out.print("1");
                System.out.print("2");
                System.out.print("3");
                System.out.print("4");
                System.out.println();
                flag = 1;
                d1.signal();
                r.unlock();
        
    }
}

7.线程组的概述和使用

  • Java中使用ThreadGroup来表示线程组,它可以对一批线程进行分类管理,Java允许程序直接对线程组进行控制。
    • 默认情况下,所有的线程都属于主线程组。
      • public final ThreadGroup getThreadGroup()//通过线程对象获取他所属于的组
      • public final String getName()//通过线程组对象获取他组的名字
    • 我们也可以给线程设置分组
      • 1,ThreadGroup(String name) 创建线程组对象并给其赋值名字
      • 2,创建线程对象
      • 3,Thread(ThreadGroup?group, Runnable?target, String?name)
      • 4,设置整组的优先级或者守护线程

public class threadGroup {
    
    public static void main(String[] args) {
        ThreadGroup tg = new ThreadGroup("自定义线程组");
        myRunnable mr = new myRunnable();
        Thread t1 = new Thread(tg, mr, "张三");
        Thread t2 = new Thread(tg, mr, "李四");
        System.out.println(t1.getThreadGroup().getName());
        System.out.println(t2.getThreadGroup().getName());
    }
}

class myRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        
    }
    
}

线程的状态

线程状态图.png

相关文章

网友评论

      本文标题:记录JAVA线程学习

      本文链接:https://www.haomeiwen.com/subject/zzwokctx.html