Java 多线程基础

Posted dweeb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 多线程基础相关的知识,希望对你有一定的参考价值。

(转载请标明出处)

一、 多线程概念

二、线程的创建和启动

三、线程的生命周期

四、控制线程

五、线程同步

六、线程通信

七、线程组和未处理的异常

八、线程池

九、线程相关类

十、快速创建两种线程

十一、定时器

 

多线程概念:

 

线程的创建和启动:

 

public class FirstThread extends Thread {
        
        private int i;
        public void run(){
            for (int i = 0; i < 100; i++) {
                System.out.println(getName()+" "+i);
            }
        }
        public static void main(String[] args) {
            for (int i = 0; i < 100; i++) {
            
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i==20){
                    new FirstThread().start();
                    new FirstThread().start();
                }
            }
        }
    }

public class SecondThread implements Runnable {
        
        private int i;
        public void run(){
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName()+" "+i);
            }
        }
      
        public static void main(String[] args) {
            for (int i = 0; i < 100; i++) {
                System.out.println(Thread.currentThread().getName()+" "+i);
                if(i==20){
                    SecondThread st = new SecondThread();
                    //通过new Thread(target , name)方法创建新线程
                    new Thread(st,"新线程1").start();
                    new Thread(st,"新线程2").start();
                }
            }
        }
    }

     ExecutorService es = Executors.newFixedThreadPool(2);

        Future<Integer> f1 = es.submit(newMyCallable(10));

        Future<Integer> f2  = es.submit(new MyCallable(20));

        System.out.println(f1.get()+" "+ f2.get());

        es.shutdown();

FutureTask<Integer> ft = new FutureTask<Integer>(new MyCallable(10));

        FutureTask<Integer> ft2 = new FutureTask<Integer>(new MyCallable(20));

        new Thread(ft,"我是线程1").start();

        new Thread(ft2,"我是线程2").start();

        System.out.println(ft.get());

public class ThirdThread {            
            public static void main(String[] args){
                //创建Callable对象
                ThirdThread rt = new ThirdThread();
                //使用Lambda表达式创建Callable<Integer>对象
                //使用FutureTask来包装Callable对象
                FutureTask<Integer> task = new FutureTask<Integer>((Callable<Integer>)() ->{
                    int i = 0;
                    for(; i < 100; i++){
                        System.out.println(Thread.currentThread().getName() + "i值:"+ i);
                    }
                    //call()方法可以有返回值
                    return i;
                });
                for (int i = 0; i < 100; i++) {
                    System.out.println(Thread.currentThread().getName()+"i值:"+ i);
                    if(i==20){
                        //实质还是以Callable对象来创建并启动线程的
                        new Thread(task,"有返回值的线程").start();
                    }
                }
                try {
                    System.out.println("子线程的返回值"+ task.get());
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }

 

 

线程的生命周期:

 

控制线程:

 

public class JoinThread extends Thread{
            
            public JoinThread(String name){
                super(name);
            }
            
            public void run(){
                for (int i = 0; i < 100; i++) {
                    System.out.println(getName() + " " +i);
                }
            }
            
            public static void main(String[] args) throws InterruptedException{
                
                new JoinThread("新线程").start();
                for (int i = 0; i < 100; i++) {
                    if(i == 20){
                        //当i==20时 jt开始启动,main线程阻塞
                        JoinThread jt = new JoinThread("被Join的线程");
                        jt.start();
                        //main线程调用了jt线程的join()方法,main线程必须等到jt执行结束
                        //才会向下执行
                        jt.join();
                    }
                    System.out.println(Thread.currentThread().getName() + " " +i);
                }
            }
        }

public class DaemonThread extends Thread{
        //后台线程的线程执行体与普通线程没有任何区别
        public void run(){
            for (int i = 0; i < 1000; i++) {
                System.out.println(getName() + " " +i);
            }
        }
        
        public static void main(String[] args) throws InterruptedException{
            
            DaemonThread dt = new DaemonThread();
            dt.setDaemon(true);
            dt.start();
            for (int i = 0; i < 10; i++) {
                System.out.println(Thread.currentThread().getName()+" "+i);
            }
            //----------程序执行到此,前台线程main线程结束------------
            //后台线程也随之结束
        }
    }

 

 

 

public class PriorityTest extends Thread{
        
        public PriorityTest(String name){
            super(name);
        }
        
        public void run(){
            for (int i = 0; i < 50; i++) {
                System.out.println(getName() + "优先级:" +getPriority()+" i:"+i);
            }
        }
        
        public static void main(String[] args) throws InterruptedException{
            
            //改变主线程的优先级
            Thread.currentThread().setPriority(6);
            for (int i = 0; i < 30; i++) {
    
                if(i == 10){
                    PriorityTest pt1 = new PriorityTest("低级");
                    pt1.start();
                    System.out.println("创建时的优先级:"+pt1.getPriority()+" i:"+i);
                    pt1.setPriority(MIN_PRIORITY);
                }
                if(i == 20){
                    PriorityTest pt2 = new PriorityTest("高级");
                    pt2.start();
                    System.out.println("创建时的优先级"+pt2.getPriority()+" i:"+i);
                    pt2.setPriority(MAX_PRIORITY);
                }
            }
        }
    }

线程同步:

 

 

public class DrawThread extends Thread{
            //模拟用户账户
            private Account account;
            //当前取钱线程所希望的取的钱数
            private double drawAmount;
            public DrawThread(String name,Account account,double drawAmount){
                super(name);
                this.account = account;
                this.drawAmount = drawAmount;
            }
            //当多个线程修改同一个共享数据时,将涉及数据安全问题
            public void run(){
                account.draw(drawAmount);
            }
            
            public static void main(String[] args) throws InterruptedException{
                Account acct = new Account("123456",1000);
                new DrawThread("甲",acct,800).start();
                new DrawThread("乙",acct,800).start();
            }
        }
        
        class Account{
            private String accountNo;
            private double balance;
            public Account(){}
            
            public Account(String accountNo, double balance){
                this.accountNo = accountNo;
                this.balance = balance;
            }
            public String getAccountNo() {
                return accountNo;
            }
            public void setAccountNo(String accountNo) {
                this.accountNo = accountNo;
            }
            //因为账户余额不允许随便修改,所以只为balance提供getter方法
            public double getBalance() {
                return balance;
            }
            //提供一个线程安全的draw()方法来完成取钱操作
            public synchronized void draw(double drawAmount){
                if(balance >= drawAmount){
                    System.out.println(Thread.currentThread().getName()+"取钱成功"+drawAmount);
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    balance -= drawAmount;
                    System.out.println("\\t余额:"+balance);
                }else{
                    System.out.println(Thread.currentThread()+"取钱失败");
                }
            }
        }

同步锁(Lock):

 

public class test02 {
            
                private final ReentrantLock lock = new ReentrantLock();
                
                public void m(){
                    //加锁
                    lock.lock();
                    try{
                            //需要保证线程安全的代码
                            //...
                    }
                    //使用finally块来保证释放锁
                    finally{
                        lock.unlock();
                    }
                }
            }

public class DeadLock implements Runnable {
            
            A a = new A();
            B b = new B();
            public void init(){
                Thread.currentThread().setName("主线程");
                a.foo(b);
                System.out.println("进入主线程");
            }
            public void run(){
                Thread.currentThread().setName("副线程");
                b.bar(a);
                System.out.println("进入副线程之后");
            }
            public static void main(String[] args) {
                DeadLock dl = new DeadLock();
                new Thread(dl).start();
                dl.init();
            }
        
        }
        class A{
            public synchronized void foo(B b){
                System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入A实例的foo()方法");
                
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用B实例的last()方法");
                b.last();
            }
            public synchronized void last(){
                System.out.println("进入A类的last()方法内部");
            }        
        }
        class B{
            public synchronized void bar(A a){
                System.out.println("当前线程名:"+Thread.currentThread().getName()+"进入B实例的bar()方法");
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("当前线程名:"+Thread.currentThread().getName()+"企图调用A实例的last()方法");
                a.last();
            }
            public synchronized void last(){
                System.out.println("进入了B类的last()方法内部");
            }
        }

public class DeadLockDemo {
        
            public static void main(String[] args) {
                
                new Thread( new DeadLock(false)).start();
                new Thread(new DeadLock(true)).start();
            }
        
        }
        class DeadLock implements Runnable{
            private static final Object objA = new Object();
            private static final Object objB = new Object();
            
            private boolean flag;
            
            public DeadLock(boolean flag){
                this.flag = flag;
            }
            
            @Override
            public void run() {
                while(true){
                    if(flag){
                        synchronized(objA){
                            System.out.println("if objA");
                            
                            synchronized(objB){
                                System.out.println("if objB");
                            }
                        }
                    }else{
                        synchronized(objB){
                            System.out.println("else objB");
                            synchronized(objA){
                                System.out.println("else objA");
                            }
                        }
                    }
                }
            }
        }

线程通信:

 

public class DrawTest {
            
            public static void main(String[] args) {
                //创建一个账户
                Account acct = new Account("123",0);
                new DrawThread("取钱者",acct,800).start();
                new DepositThread("存钱者1", acct, 800).start();
                new DepositThread("存钱者2", acct, 800).start();
                new DepositThread("存钱者3", acct, 800).start();
            }
        }
        
        class Account{
            private String accountNo;
            private double balance;
            //标识账户中是否已经有存款的旗标
            private boolean flag = false;
            public Account(){}
            
            public Account(String accountNo, double balance){
                this.accountNo = accountNo;
                this.balance = balance;
            }
        
            public String getAccountNo() {
                return accountNo;
            }
        
            public void setAccountNo(String accountNo) {
                this.accountNo = accountNo;
            }
        
            //因为账户余额不允许随便修改,所以只为balance提供getter方法
            public double getBalance() {
                return balance;
            }
            
            //提供一个线程安全的draw()方法来完成取钱操作
            public synchronized void draw(double drawAmount){
                try {
                    if(!flag){
                        wait();
                    }else{
                        //执行取钱操作
                        System.out.println(Thread.currentThread().getName()+"取钱"+drawAmount);
                        balance -= drawAmount;
                        System.out.println("账户余额为:"+balance);
                        flag = false;
                        //唤醒其他线程
                        notifyAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            
            public synchronized void deposit(double depositAmount){
                try {
                    //flag为true 表示账户已有人存钱进去,存钱方法阻塞
                    //当while判断后,wait()方法释放锁,唤醒其他线程去存钱,当存取次数相同时,此程序不会阻塞
        //            while(flag){
        //                wait();
        //            }
                    if(flag){
                        wait();
                    }else{
                        //执行存款操作
                        System.out.println(Thread.currentThread().getName()+"存款:"+ depositAmount);
                        balance += depositAmount;
                        System.out.println("账户余额:"+balance);
                        flag = true;
                        notifyAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        
        class DrawThread extends Thread{
            //模拟用户取钱
            private Account account;
            //当前取钱线程所希望取的钱数
            private double drawAmount;
            public DrawThread(String name,Account account,double drawAmount){
                super(name);
                this.account = account;
                this.drawAmount = drawAmount;
            }
            public void run(){
                for (int i = 0; i < 300; i++) {
        
                    System.out.println("取钱次数"+i);
                    account.draw(drawAmount);
                }
            }
        }
        
        class DepositThread extends Thread{
            //模拟用户账户
            private Account account;
            //当前存钱线程所希望存的钱数
            private double depositAmount;
            public DepositThread(String name , Account account , double depositAmount){
                super(name);
                this.account = account;
                this.depositAmount = depositAmount;
            }
            public void run(){
                for (int i = 0; i < 100; i++) {
                    account.deposit(depositAmount);
                }
            }
        }

class Account{
            
            //显示定义Lock对象
            private final Lock lock = new ReentrantLock();
            //获得指定Lock对象对应的Condition
            private final Condition cond = lock.newCondition();
            
            private String accountNo;
            private double balance;
            //标识账户中是否已经有存款的旗标
            private boolean flag = false;
            public Account(){}
            
            public Account(String accountNo, double balance){
                this.accountNo = accountNo;
                this.balance = balance;
            }
        
            public String getAccountNo() {
                return accountNo;
            }
        
            public void setAccountNo(String accountNo) {
                this.accountNo = accountNo;
            }
        
            //因为账户余额不允许随便修改,所以只为balance提供getter方法
            public double getBalance() {
                return balance;
            }
            
            //提供一个线程安全的draw()方法来完成取钱操作
            public  void draw(double drawAmount){
                lock.lock();
                try {
                    if(!flag){
                        cond.await();
                    }else{
                        //执行取钱操作
                        System.out.println(Thread.currentThread().getName()+"取钱"+drawAmount);
                        balance -= drawAmount;
                        System.out.println("账户余额为:"+balance);
                        flag = false;
                        //唤醒其他线程
                        cond.signalAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally{
                    lock.unlock();
                }
            }
            
            
            public  void deposit(double depositAmount){
                lock.lock();
                try {
                    //flag为true 表示账户已有人存钱进去,存钱方法阻塞
                    //当while判断后,wait()方法释放锁,唤醒其他线程去存钱,当存取次数相同时,此程序不会阻塞
        //            while(flag){
        //                wait();
        //            }
                    if(flag){
                        cond.await();
                    }else{
                        //执行存款操作
                        System.out.println(Thread.currentThread().getName()+"存款:"+ depositAmount);
                        balance += depositAmount;
                        System.out.println("账户余额:"+balance);
                        flag = true;
                        cond.signalAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                finally{
                    lock.unlock();
                }
            }
        }
        
        class DrawThread extends Thread{
            //模拟用户取钱
            private Account account;
            //当前取钱线程所希望取的钱数
            private double drawAmount;
            public DrawThread(String name,Account account,double drawAmount){
                super(name);
                this.account = account;
                this.drawAmount = drawAmount;
            }
            public void run(){
                for (int i = 0; i < 300; i++) {
        
                    System.out.println("取钱次数"+i);
                    account.draw(drawAmount);
                }
            }
        }

public class BlockingQueueTest {
        
            public static void main(String[] args) {
                //创建一个容量为1的BlockingQueue以上是关于Java 多线程基础的主要内容,如果未能解决你的问题,请参考以下文章

java基础入门-多线程同步浅析-以银行转账为样例

java多线程基础

Java基础之多线程

Java多线程基础

多线程编程学习一(Java多线程的基础)

Java 多线程基础多线程的实现方式