多线程基础知识

   日期:2020-09-20     浏览:94    评论:0    
核心提示:多线程基础知识的学习什么是多线程?基本概念多线程的创建方式继承Thread类和实现Runable接口两种方式的对比如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入什么是多线程?你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Mark

多线程基础知识的学习

  • 基本概念
  • 多线程的创建方式
  • 多线程的常用方法
  • 多线程的生命周期
  • 线程的安全问题
    • 解决线程的安全问题
    • 线程安全的单例模式之懒汉式
    • 线程中的死锁问题
    • 线程的通信

基本概念

  1. 程序: 为完成特定任务,用某种语言编写的一组指令的集合,即指一段静态的代码,静态对象;
  2. 进程: 是程序的一次执行过程,或是正在运行的一个程序,是一个动态的过程:有它自身的产生、存在和消亡的过程----生命周期;
  3. 线程 : 进程可以进一步细化为线程,是程序内部的一条执行路径,一个程序可以有多条执行路径;

程序是静态的,进程是动态的;

进程作为资源分配单位,系统在运行时会为每个进程分配不同的内存区域;

线程作为调度和执行的单位,每个线程拥有独立的运行栈和程序计数器;

一个进程中的多个线程共享相同的内存单元/内存地址空间–它们从同一堆中分配对象,可以访问相同的变量和对象,这就是线程间的通信更加的简便、高效,但是多线程操作共享的系统资源可能带来安全隐患;

多线程的创建方式

面试题:创建多线程的方式有几种?
答:四种;
1). 继承Thread类的方式创建线程;
2). 实现Runnable接口创建线程;
3). 使用Callable和Future创建线程;
4). 使用线程池例如用Executor框架;

1.继承Thread类的方式创建线程:

public class Main01 { 

    public static void main(String[] args) { 
        //给主线程命名:Thread.currentThread()是获取当前线程
        Thread.currentThread().setName("主线程");
        //打印
        System.out.println(Thread.currentThread().getName()+"线程执行了");
        //创建一个线程
        MyThread myThread = new MyThread();
        //启动线程
        myThread.start();
    }
}

class MyThread extends Thread{ 
    @Override
    public void run() { 
        System.out.println(Thread.currentThread().getName()+"线程执行了");
    }
}
//输出
 	主线程线程执行了
	Thread-0线程执行了

2.实现Runnable接口的方式创建线程:

public class Main02 { 

    public static void main(String[] args) { 
        //给main线程命名
        Thread.currentThread().setName("主线程");
        //打印
        System.out.println(Thread.currentThread().getName()+"执行了");

        //创建线程
        MyRunnable myRunnable = new MyRunnable();
        //将myRunnable传入Thread;类中
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

class MyRunnable implements Runnable{ 

    @Override
    public void run() { 
        System.out.println(Thread.currentThread().getName()+"执行了");
    }
}
//输出
 	主线程线程执行了
	Thread-0线程执行了

3.使用Callable和FutureTask创建线程

public class Main03 { 
    public static void main(String[] args) throws ExecutionException, InterruptedException { 
   		 //创建实现类
        MyCallable myCallable = new MyCallable();
		//创建FutureTask类,该类实现了Runnable接口;
        FutureTask stringFutureTask = new FutureTask(myCallable);
        //将创建的FutureTask的实例传递给Thread类,并启动线程
        new Thread(stringFutureTask).start();

        Object o = stringFutureTask.get();

        System.out.println(o);


    }
}
//MyCallable接口实现Callable接口,其中的call方法相当于我们的run方法
class MyCallable implements Callable{ 

    @Override
    public Object call() throws Exception { 
        int h = 0;
        for(int i = 1; i <100; i++){ 
            if(i % 2 == 0){ 
                h+=i;
            }
        }
        return  Thread.currentThread().getName()+"求和为:--"+h;
    }
}

4.使用线程池

public class Main04 { 

    public static void main(String[] args) { 
        //1.提供指定线程数量的线程池;
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        //2.执行指定的线程操作,需要提供实现Runnable接口和Callable接口的实现类对象;
        executorService.execute(new MyRunnable1());

        //关闭连接池;
        executorService.shutdown();

    }
}
class MyRunnable1 implements Runnable { 
    @Override
    public void run() { 

        System.out.println("这是使用线程池创建线程");

    }
}
使用线程池的好处:
	1.提高响应速度(减少了线程的创建时间)
	2.降低了资源消耗(重复利用线程池中的线程,不需要每次都创建)
	3.便于管理:	
		corePoolSize:核心池的大小
		maximumPoolSize:最大线程数;
		keepAliveTime:线程没有任务是最多保持多长时间后终止

多线程的常用方法

1.start():启动当前线程;调用当前线程的run();
2.run(): 通常需要重写Thread类中的此方法,将要执行的操作写入该方法中;
3.currentThread(): 静态方法,返回执行当前代码的线程;
4.getName():获取当前线程的名字;
5.setName():设置当前线程的名字;
6.yield():释放当前cpu的执行权;
7.join():在线程A中调用线程B的join(),此时线程A就会进入阻塞状态,直到线程B完全执行完以后,线程A才结束阻塞状态;
8.stop():已过时,当执行此方法是,强制结束当前线程;
9.sleep(long millitime) : 使当前线程睡眠指定的毫秒数,在此期间,该线程处于阻塞状态;
10. isAlive(): 判断当前线程是否存活;

多线程的生命周期

线程的安全问题

1.多个线程执行的不确定性造成执行结果的不稳定
2.多个线程对账本的共享,会造成操作的不完整性,会破坏数据;

解决线程的安全问题

解决线程安全的方式有几种?
答:3种;
1.同步代码块—synchronized(同步监视器){需要被同步的代码}

public class SYNdemo01 { 

    public static void main(String[] args) { 

        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread(myRunnable);
        Thread thread2 = new Thread(myRunnable);

        thread1.start();
        thread2.start();

    }
}
class MyRunnable implements Runnable{ 
    private int x = 150;
    @Override
    public void run() { 
        while (true){ 
            
            synchronized (this){ 
                if(x>0){ 
                    try { 
                        Thread.currentThread().sleep(100);
                    } catch (InterruptedException e) { 
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"窗口卖出了:"+x+"号票");
                    x--;
                }else{ 
                    break;
                }
            }
        }
    }
}
synchronized(){ 需要被同步的代码}
	1.操作共享数据的代码,即需要被同步的代码;
	2.共享数据,多个线程同时操作的变量,比如我们现实中的火车票
	3.同步监视器:俗称:,任何一个类的对象,都可以充当锁对象;
		要求:多个线程必须要共用一把锁,即这个锁对象在多线程操作时必须是同一个锁对象;

2.同步方法—被synchronized修饰的方法

public class SYNdemo01 { 

    public static void main(String[] args) { 

        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread(myRunnable);
        Thread thread2 = new Thread(myRunnable);

        thread1.start();
        thread2.start();

    }
}
class MyRunnable implements Runnable{ 
    private int x = 150;
    @Override
    public void run() { 
        while (true){ 

            loket();
            if(x<=0){ 
                break;
            }
            
        }
    }

    //同步方法
    public synchronized void loket(){ 
        if(x>0){ 
            try { 
                Thread.currentThread().sleep(100);
            } catch (InterruptedException e) { 
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+"窗口卖出了:"+x+"号票");
            x--;
        }

    }
}

3.Lock锁解决线程安全问题
Lock锁是JDK5.0后加入的,是一个接口,比较常用的是ReentrantLock类,他拥有与synchronized相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁;

public class LockSuo { 

    public static void main(String[] args) { 
        Window window = new Window();
        Thread thread1 = new Thread(window);
        Thread thread2 = new Thread(window);

        thread1.start();
        thread2.start();
    }
}

class Window implements  Runnable{ 

    private static int x = 150;
    private ReentrantLock reentrantLock = new ReentrantLock();
    @Override
    public void run() { 
        while (true){ 
            try{ 
                reentrantLock.lock();

                if(x>0){ 

                    try { 
                        Thread.currentThread().sleep(100);
                    } catch (InterruptedException e) { 
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+"窗口出售了:"+x+"号票");
                    x--;
                }else{ 
                    break;
                }
            }finally { 
                reentrantLock.unlock();
            }
        }
    }
}

线程安全的单例模式之懒汉式

class BankTest{ 
    private static BankTest bankTest;

    private BankTest(){ 

    }
    public static BankTest getBankTest(){ 
        synchronized (BankTest.class) { 
            if (bankTest == null) { 

                bankTest = new BankTest();
            }
        }
        return bankTest;
    }
}

线程中的死锁问题

死锁: 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁;
死锁出现后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续;
死锁演示:

public class SYNdemo02 { 
    public static void main(String[] args) { 

        StringBuffer s1 = new StringBuffer();
        StringBuffer s2 = new StringBuffer();

        new Thread(){ 
            @Override
            public void run() { 
                synchronized (s1){ 
                    s1.append("a");
                    s2.append("1");
                    try { 
                        Thread.currentThread().sleep(1000);
                    } catch (InterruptedException e) { 
                        e.printStackTrace();
                    }
                    synchronized (s2){ 
                        s1.append("b");
                        s2.append("2");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();
        new Thread(){ 
            @Override
            public void run() { 
                synchronized (s2){ 
                    s1.append("c");
                    s2.append("3");
                    try { 
                        Thread.currentThread().sleep(1000);
                    } catch (InterruptedException e) { 
                        e.printStackTrace();
                    }
                    synchronized (s1){ 
                        s1.append("d");
                        s2.append("4");

                        System.out.println(s1);
                        System.out.println(s2);
                    }
                }
            }
        }.start();
    }
}

线程的通信

例题:交替打印1-100;线程1和线程2交替打印;

public class JT { 
    public static void main(String[] args) { 

        Number number = new Number();
        Thread thread1 = new Thread(number);
        Thread thread2 = new Thread(number);

        thread1.start();
        thread2.start();
    }
}

class Number implements  Runnable { 
    private static int x = 1;
    
    @Override
    public void run() { 
        while (true) { 
           synchronized (this) { 
               if (x <= 100) { 
                   notify();
                   try { 
                       Thread.currentThread().sleep(100);
                   } catch (InterruptedException e) { 
                       e.printStackTrace();
                   }
                   System.out.println(Thread.currentThread().getName() + "打印了:" + x);
                   x++;
                   try { 
                       wait();
                   } catch (InterruptedException e) { 
                       e.printStackTrace();
                   }
               } else { 
                   break;
               }
           }

        }

    }
}
 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服