鱼C论坛

 找回密码
 立即注册
查看: 2431|回复: 0

[学习笔记] Java030-线程基础

[复制链接]
发表于 2019-1-13 14:22:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 moc 于 2019-1-13 14:21 编辑

1、简介
进程: 正在运行的程序,是系统进行资源分配和调用的独立单位,每一个进程都有它自己的内存空间和系统资源,详见入口
线程: 是进程中的单个顺序控制流,是一条执行路径,线程不能独立存在,依附于进程。
Java程序至少有两个线程:  主线程 + 垃圾回收线程
线程的生命周期:
java-thread.jpg

新建状态:
        使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
就绪状态:
        当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
运行状态:
        如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
阻塞状态:
        如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
        ① 等待阻塞: 运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
        ② 同步阻塞: 线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。
        ③ 其他阻塞: 通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
死亡状态:
        一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。
2、线程实现方式1: 继承Thread类
步骤:
        ① 自定义类MyThread继承Thread类;
        ② MyThread类里面重写run();
        ③ 创建MyThread类的对象,即线程对象;
        ④ 启动线程,调用线程对象的start()方法。
注意:
        ① run():仅仅是封装被线程执行的代码,直接调用是普通方法
        ② start():首先启动了线程,然后再由jvm去调用该线程的run()方法
获取设置线程名
public static Thread currentThread() ------------>  返回当前正在执行的线程对象
public final String getName()  --------------------->  获取线程的名称        
public final void setName(String name) --------->  设置线程的名称
举例:
// 线程类
public class MyThread extends Thread {        
        public MyThread() {
        }
        
        public MyThread(String name){
                super(name);
        }

        @Override
        public void run() {
                for (int x = 0; x < 20; x++) {
                        System.out.println(x);
                }
        }
}
// 线程测试类
public class MyThreadDemo {
        public static void main(String[] args) {
                // 创建线程对象 --- 无参构造+setXxx()
                MyThread my1 = new MyThread();
                my1.setName("Ubuntu");     //调用方法设置名称
                my1.start();
                
                // 创建线程对象 --- 带参构造方法
                MyThread my2 = new MyThread("Centos");
                my2.start();
                
                System.out.println(Thread.currentThread().getName());
        }
}
3、线程控制
1. 守护线程(后台线程)
守护线程与普通线程的唯一区别是:当JVM中所有的线程都是守护线程的时候,JVM就可以退出了;如果还有一个或以上的非守护线程则不会退出。(以上针对正常退出,调用System.exit必定会立即退出)
方法:   public final void setDaemon(boolean on)
MyThread my3 = new MyThread("RedHat");
my3.setDaemon(true);
my3.start();
2. 线程休眠
Thread类静态方法,让线程进程一定时间的阻塞状态,时间结束后处于就绪状态争夺CPUI执行权。
方法:     public static void sleep(long millis)
3. 线程加入
等待该线程终止,在进行其他线程的执行。
方法:   public final void join()
MyThread my4 = new MyThread("openSuSE");
MyThread my5 = new MyThread("Linux Mint");
my4.start();
try {
        my4.join();
} 
catch (InterruptedException e) {
        e.printStackTrace();
}
my5.start();
4. 线程礼让
Thread类静态方法,暂停当前正在执行的线程对象,并执行其他线程。
让多个线程的执行更和谐,但是不能靠它保证一个线程一次。
方法:   public static void yield()
public class ThreadYield extends Thread {
        @Override
        public void run() {
                for (int x = 0; x < 100; x++) {
                        System.out.println(getName() + ":" + x);
                        Thread.yield();    // 线程礼让
                }
        }
}
5. 中断线程
把线程的状态终止,并抛出一个InterruptedException。
方法:     public void interrupt()
MyThread my6 = new MyThread("Debian");
my6.start();
// 线程超过三秒不醒过来,就中断线程 (最多允许该线程允许3s)
try {
        Thread.sleep(3000);
        my6.interrupt();
} 
catch (InterruptedException e) {
        e.printStackTrace();
}
6. 线程优先级
        ① 每一个 Java 线程都有一个优先级< 默认NORM_PRIORITY(5)>,这样有助于操作系统确定线程的调度顺序。
        ② Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )
        ③ 具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。
方法:
public final int getPriority()  --------------------------> 返回线程对象的优先级
public final void setPriority(int newPriority) --------> 更改线程的优先级。
MyThread my7 = new MyThread("Fedora");
MyThread my8 = new MyThread("Solus OS");

System.out.println(my7 .getPriority());
my8.setPriority(2);

my7.start();
my8.start();
4、线程实现方式2: 实现Runnable接口
步骤:
        ① 自定义类MyRunnable实现Runnable接口;
        ② 重写run()方法;
        ③ 创建MyRunnable类的对象;
        ④ 创建Thread类的对象,并把③步骤的对象作为构造参数传递。
// Runnable接口实现类
public class MyRunnable implements Runnable {
        @Override
        public void run() {
                for (int x = 0; x < 100; x++) {
                        // 由于实现接口的方式就不能直接使用Thread类的方法了,但是可以间接的使用
                        System.out.println(Thread.currentThread().getName() + ":" + x);
                }
        }
}
// Runnable实现类测试
public class MyRunnableDemo {
        public static void main(String[] args) {
                MyRunnable my = new MyRunnable();  // 创建MyRunnable类的对象

                // 创建Thread类的对象,并把③步骤的对象作为构造参数传递                
                Thread t1 = new Thread(my);     // Thread(Runnable target)
                t1.setName("Windows");;
                Thread t2 = new Thread(my, "Linux");   // Thread(Runnable target, String name)

                t1.start();
                t2.start();
        }
}

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-5 21:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表