Java学习——线程


一、线程是什么?

线程:Thread,是Java程序执行的发动机。就是线程运行着我们的代码。
进程:Process,一个程序就是操作系统的一个进程,一个进程下可以有很多线程。

线程的执行:线程其实就是执行一个入口方法,执行完毕就结束了。比如main方法是主线程。
线程在执行方法的时候,每次遇到方法调用,都会给当前的线程栈增加一层,这一层里保存的,就是线程当前的执行状态,比如当前方法的局部变量的值,当前方法执行到哪里了等。
所以线程栈里的每一条,都是方法已经开始执行但是还没有结束的方法,没有结束时因为它代码还没执行完,或者时在等待其调用的方法执行完。

二、创建自己的线程

打印一段文字,每打印一个字休眠

public class CreateThreadAppMain {

    private static final String TEXT = "窗外的麻雀,在电线杆上多嘴,你说这一句,很多夏天的感觉,手中的铅笔,在纸上来来回回............";

    public static void main(String[] args) {
        // TODO 代码是被线程执行的,任何代码都可以通过Thread.currentThread()获取执行当前代码的线程
        System.out.println("程序开始,执行的线程名字叫做" + Thread.currentThread().getName());

        // TODO 改成2试试看?
        for (int i = 1; i <= 1; i++) {
            // TODO 学习创建线程的方法
            // TODO Runnable接口里的run是线程执行的方法,执行完毕,线程就结束了
            // TODO 理解代码是在线程里被执行的,同样的代码可以被多个线程执行。
            // TODO 暂停一下 Java ,看看有多少线程,每个线程的名字等信息
            Thread thread = new Thread(new PrintStoryRunnable(TEXT, 200 * i), "我的线程-" + i);
            // TODO 创建好线程之后,如果要启动线程,必须调用start方法,注意不是run方法
            thread.start();
        }

        System.out.println("启动线程结束,名字叫做" + Thread.currentThread().getName());
    }

    static class PrintStoryRunnable implements Runnable {
        private String text;
        private long interval;

        public PrintStoryRunnable(String text, long interval) {
            this.text = text;
            this.interval = interval;
        }

        @Override
        public void run() {
            try {
                double num = Math.random();
                System.out.println("执行这段代码的线程名字叫做" + Thread.currentThread().getName());
                printSlowly(text, interval);
                System.out.println(Thread.currentThread().getName() + "执行结束");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static void printSlowly(String text, long interval) throws InterruptedException {
        for (char ch : text.toCharArray()) {
            Thread.sleep(interval);
            System.out.print(ch);
        }
        System.out.println();
    }
}

如果把上面代码的for循环,改成循环多次,则创建了多个线程,如果时间也是不一样的,则此时打印出来的文字是混乱的。
在这里插入图片描述
线程状态
在这里插入图片描述

三、同步控制之synchronized

synchronized关键字用来修饰成员方法,代表这个方法对于同一个对象来说,同一时间只允许一个线程执行,别的线程如果也调用这个实例的这个方法,就需要等待已经在执行这个方法的线程执行完毕,才能进入方法执行。
饿汉式的单例模式是线程安全的,因为初始化的时候只创建一次。而懒汉式的单例模式是非线程安全的,这个时候可以用到synchronized上锁:

public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {
    }

    public static Singleton getInstance() {
    	// 第一次判空是保证初始化之后的所有线程,不需要等待锁
        if (instance == null) {
            synchronized (Singleton.class) {
            	// 第二次判空是多线程竞争锁,拿到锁的先初始化,后拿到锁的无需再进去初始化。(保证对象为空才去创建)
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

四、线程池

线程池(thread pool):一种线程使用模式。创建线程和销毁线程的花销是比较大的,需要多个线程时,一个一个创建,使用完了再销毁,这样带来过多的开销。而线程池可以维护多个线程,有任务的线程放入任务队列,空闲线程放入空闲队列等待任务,可以把创建和销毁的线程的过程去掉。

使用线程池的优势:

  1. 提高效率,创建好一定数量的线程放在池中,等需要使用的时候就从池中拿一个,这要比需要的时候创建一个线程对象要快的多。
  2. 减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。
  3. 提升系统响应速度,假如创建线程用的时间为T1,执行任务用的时间为T2,销毁线程用的时间为T3,那么使用线程池就免去了T1和T3的时间
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值