Java学习记录 线程篇

线程与进程

线程 是进程中的执行过程,一个进程包含有多个线程,并发执行

进程 是一个运行的应用程序,每个进程都有自己独立的内存空间。在Windows系统中,一个运行的exe(应用程序)就是一个进程

实现线程

实现线程线程主要有 java.lang.Thread类Runnable接口

Thread类

Class Thread

java.lang.Object
java.lang.Thread

Thread类中实例化的对象代表线程,启动需要Thread实例

常用构造方法

Thread()
Thread(String name)

name: 自定义线程名

常用方法

修饰符方法说明
ThreadcurrentThread()返回对当前正在执行的线程对象的引用
longgetId()返回线程标识符
StringgetName() 返回线程名称
intgetPriority() 返回线程的优先级
Thread.StategetState() 返回线程的状态
voidinterrupt() 中断线程
booleanisAlive() 线程是否运行
booleanisInterrupted() 线程是否被中断
voidrun() 调用该Runnable对象的run方法
voidstart() 线程开始执行run方法
voidsleep(long ms) 线程以指定的毫秒数暂停(等待)
voidjoin() 在线程中加入另一个线程
booleaninterrupted() 中断线程
voidsetPriority(int newPriority) 设置线程的优先级newPriority的范围(1-10)
voidsetDaemon(boolean on)是否设置守护线程。守护线程:主线程结束,子线程也跟着结束
StringtoString() 返回线程的字符串表示、线程的名、优先级、线程组

点击代码示例* (Thread操作)

Runnable接口

线程一般通过Thread类创建的。但 Runnable接口 也可以实现进程

优点

  • 适合多线程同时执行相同的任务
  • 不受 类的单继承约束

实现方式

Thread(Runnable target)
Thread(Runnable target , String name)

target: 启动线程时调用,run方法
name: 自定义线程名

点击代码示例* (Runnable操作)

Callable接口

Runnable接口 比 Callable接口 少了 线程结束无返回值 和 不能抛出异常 ,而 Callable接口 正是弥补这一缺陷!

使用步骤

//1. 编写 Callable接口 , 实现 call抽象方法
class MyCallable implements Callable<T>{
    @Ovrride
    public <T> call() throws Exception{
        return T;
    }
}
//2. 创建FutureTask对象,并传入第一步编写的Callable类对象
FutureTask<T> future = new FutureTask<>(callable);
//3. 通过Thread,启动线程
new Thread(future).start();
//4. 获取返回值,FutureTask对象中的get()方法获取返回值(此方法有堵塞效果)
future.get();

FutureTask类 说明:用于异步获取执行结果或取消执行任务的作用(线程池的核心)

点击代码示例* (Callable操作)

线程生命周期

线程具有生命周期,有7种分别为:出生状态、就绪状态、运行状态、休眠状态、阻塞状态、死亡状态

周期的说明:

出生状态(New): 线程创建后到线程的start()方法前
就绪状态(Runnable): 可执行状态,当线程获取系统资源就进入运行状态
运行状态(Running): run()方法,没有意外线程则一直运行到结束
休眠状态(Sleep): 执行sleep()方法休眠(等待)
阻塞状态(Blocked): 等待用户 输入/输出 ,用户 输入/输出 结束后进入就绪状态
死亡状态(Dead): 线程的run()方法执行完毕,则进入死亡状态

Windows操作系统中,会为每个线程分配一小段CPU时间片,一旦CPU时间片结束会切换到下一线程

再次进入运行状态:

  • 线程调用notify()方法(唤醒线程)
  • 线程调用notifyAll()方法(唤醒线程)
  • 线程调用interrupt()方法(中断线程)
  • 线程的休眠时间结束
  • 输入/输出 结束

线程方法

线程休眠

sleep(long ms) 方法 停止多少秒。它可能会抛出InterruptedException异常,所以放在try-catch块中。暂停后醒来,不能保证它能立即运行!

//休眠1s
Thread.sleep(1000); 

线程加入

join() 方法 加入线程。当一个线程执行中,join()方法可使另一个线程加入,线程需要等另一个线程执行完才可以继续执行原旧的线程!
join(long millis , int nanos)

millis: 等待另一个线程的时间(秒
nanos: 另一个线程的死亡时间(纳秒

//加入ThreadB线程
··· run(){  //线程执行中
    while(true){
        //加入另一个线程
        ThreadB.join();
    }
}

线程中断

interrupted() 方法 中断线程。 能使线程离开run()方法,同时结束线程,但会抛出InterruptedException异常!

//终止线程:ThreadA
ThreadA.interrupted();

唤醒线程

notify()
唤醒正在等待的单个线程
notifyAll()
唤醒正在等待的所有线程
wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法

wait/notify方法的调用必须处在该对象的锁中,在调用这些方法时首先需要获得该对象的锁,需要配合同步使用,以防多线程错乱

线程礼让

yield() 方法 线程礼让,给当前运行状态的线程提个醒,告知它可以将资源礼让给其他线程。但目前情况没有机制能保证当前线程会礼让将资源分配!(操作系统会自动分配CPU时间片执行 (不常用

线程优先级

每个线程都有自己的优先级,线程的优先级代表着该线程的重要性。多个处于就绪的线程就能体现优先级的作用!

Thread类中包含成员变量代表有:
Thread.MAX_PRIORITY = 10 (常量10
Thread.MIN_PRIORITY = 1 (常量1
Thread.NORM_PRIORITY = 5 (默认5

setPriority(int newPriority) 方法 进程优先级调整。调整线程的优先级的情况newPriority范围(0-10)

点击代码示例* (线程优先级)

线程同步

多线程执行程序,会出现线程抢资源的现象,该现象会导致数据脏读!为了防止多线程的冲突,JAVA提供了线程同步的机制来防止资源抢占的问题!

synchronized关键字

synchronized关键字采用定时只允许一个线程访问共享资源 (道理跟上排队上厕所一样

同步块

每个对象都有标志位,它具有0和1两个值。0代表同步块中在运行其他线程;1代表该线程能被同步块执行,执行中途并将Object对象的标志位设置为0,防止其他线程执行同步块中的代码。(一个线程运行到同步块时首先检查该对象的标志位)

synchronized(Object){
    ···
}
//Object:任意对象,仅作为标志(相当于一把锁,多人使用的锁)

点击代码示例* (synchronized安全线程)

同步方法

在自定义方法 前面修饰 synchronized关键字 形成同步方法。
某对象调用同步方法时,该对象的其他同步方法必须等待该同步方法执行完毕后才能被执行。必须将每个能访问共享资源的方法修饰为synchronized,否则会报错!

点击代码示例* (synchronized方法安全线程)

显示锁

Class ReentrantLock
java.lang.Object
java.util.concurrent.locks.ReentrantLock

实现接口
Serializable , Lock

ReentrantLocksynchronized 又 称隐式锁 或 显示锁,它们在使用上没有什么区别 ,但ReentrantLock 可更直观的体现锁的概念。 synchronized 则是隐式实现锁的概念。

构造方法
ReentrantLock()
ReentrantLock(boolean fair)

fair: 公平锁

方法

返回方法说明
intgetHoldCount()查询当前线程对锁的停止数量
intgetQueueLength()获取锁的线程数 估数
intgetWaitQueueLength(Condition condition)获取与此锁相关条件等待的线程
booleanhasQueuedThread(Thread thread)查询指定线程是否获取锁
booleanhasQueuedThreads()查询是否有线程等待锁
booleanhasWaiters(Condition condition)查询是否有相关条件等待的锁
booleanisFair()是否为锁的公平,启动则true
booleanisHeldByCurrentThread()查询锁是否是当前线程持有
booleanisLocked()查询锁是否有线程持有
voidlock()锁定锁(上锁)
voidlockInterruptibly()锁定锁
StringtoString()返回标识锁的字符串内容
booleantryLock()
booleantryLock(long timeout, TimeUnit unit)指定时间范围,
voidunlock()释放锁(解锁)

点击代码示例* (ReentrantLock安全线程)

线程池

ExecutorService接口

继承接口
Executor

实现类
AbstractExecutorService , ForkJoinPool , ScheduledThreadPoolExecutor , ThreadPoolExecutor

线程的集合称为线程池

频繁多线程操作会影响效率。反复的 创建 、关闭 线程会需要大量时间!可减少时间 和 资源的浪费!

线程池原理图

缓存线程池

  • 无长度限制
  • 自动扩容空间

点击代码示例* (缓存线程池)

定长线程池

  • 自定 固定 长度
  • 无闲线程 空间未满 自动扩容
  • 无闲线程 空间已满 等待空闲

点击代码示例* (定长线程池)

单线程线程池

  • 只有一个线程
  • 无闲线程 等待

点击代码示例* (单线程线程池)

周期性任务定长线程池

  • 可指定长度
  • 无闲线程 空间未满 自动扩容
  • 无闲线程 空间已满 等待空闲
  • 定时执行、周期执行

点击代码示例* (周期性任务定长线程池)

代码索引

File操作

返回*

public class Demo {
    public static void main(String[] args) {
        
        //实例对象
        Thread a = new MyThreadA();
        Thread b = new MyThreadB();
        
        /**其他方法测试*/
        System.out.println("==========");
        System.out.println("a.getId():"+a.getId());
        System.out.println("a.getName():"+a.getName());
        System.out.println("a.getPriority():"+a.getPriority());
        System.out.println("a.getState():"+a.getState());
        System.out.println("a.isAlive():"+a.isAlive());
        System.out.println("a.isInterrupted():"+a.isInterrupted());
        System.out.println("a.toString():"+a.toString());
        System.out.println("==========");
        
        //执行线程(双线程执行,同时执行)
        /**线程A*/
        a.start();
        /**线程B*/
        b.start();
        
        /**
         
        以下代码为运行a对象的run()方法再执行b对象run()方法
        a.run();
        b.run();
        
        */
        
    }
}

class MyThreadA extends Thread{
    @Override
    public void run() {
        for (int i = 0; i < 26; i++) {
            System.out.print("A:"+i);
            /**休眠1秒(等待)*/
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
}

class MyThreadB extends Thread{
    @Override
    public void run() {
        for (char i = 'a'; i < 'z'; i++) {
            System.out.println("B:"+i);
            /**休眠1秒(等待)*/
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    
}



/**运行结果

==========
a.getId():13
a.getName():No.1
a.getPriority():5
a.getState():NEW
a.isAlive():false
a.isInterrupted():false
a.toString():Thread[No.1,5,main]
==========
 B:a
 A:0
 B:b
 A:1
 B:c
 A:2
 A:3
 B:d
 B:e
 A:4
 A:5
 B:f
 A:6
 B:g
 A:7
 B:h
 A:8
 B:i
 B:j
 A:9
 A:10
 B:k
 A:11
 B:l
 A:12
 B:m
 B:n
 A:13
 A:14
 B:o
 B:p
 A:15
 B:q
 A:16
 B:r
 A:17
 B:s
 A:18
 A:19
 B:t
 B:u
 A:20
 A:21
 B:v
 A:22
 B:w
 B:x
 A:23
 B:y
 A:24
 A:25
 
 */

Runnable操作

返回*

public class MainStartRunnable {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable() , "A");
        Thread t2 = new Thread(new MyRunnable() , "B");
        Thread t3 = new Thread(new MyRunnable() , "C");
        
        t.start();
        t2.start();
        t3.start();
        
    }
} 
class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0 ; i < 10 ; i++) {
            System.out.println(Thread.currentThread().getName()+" : "+i);
        }
    }
}

/*

B : 0
A : 0
A : 1
A : 2
A : 3
A : 4
A : 5
A : 6
A : 7
A : 8
A : 9
B : 1
B : 2
B : 3
B : 4
B : 5
B : 6
B : 7
B : 8
B : 9
C : 0
C : 1
C : 2
C : 3
C : 4
C : 5
C : 6
C : 7
C : 8
C : 9


*/

Callable操作

返回*

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class Demo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable callable = new MyCallable();
        FutureTask<Integer> future = new FutureTask<>(callable);
        new Thread(future).start();
        System.out.println("线程返回 : "+future.get());
        System.out.println("堵塞测试!!!");
    }
    
    static class MyCallable implements Callable<Integer>{
        int num = 0;
        
        //返回的方法
        @Override
        public Integer call() throws Exception {
            for (int i = 1 ; i <= 100 ; i++) {
                num += i;
                System.out.println(Thread.currentThread().getName()+" : "+i);
            }
            return num;
        }
        
    }
}

/*

Thread-0 : 1
Thread-0 : 2
Thread-0 : 3
····
Thread-0 : 100
线程返回 : 5050

*/

synchronized安全线程

返回*

public class Demo {
    
    public static void main(String[] args) {
        Runnable t = new Ticket();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }
    
    static class Ticket implements Runnable{
    
        private int count = 10;
        private final Object o = new Object();
        
        @Override
        public void run() {
            while (true){
                synchronized (o){
                    if (count > 0){
                        
                        //如果synchronized套在这里 , 多线程会错读
                        
                        System.out.println(Thread.currentThread().getName()+" : "+ --count);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else {
                        break;
                    }
                }
            }
        }
        
    }
}

/*

Thread-2 : 9
Thread-2 : 8
Thread-2 : 7
Thread-0 : 6
Thread-1 : 5
Thread-0 : 4
Thread-2 : 3
Thread-0 : 2
Thread-1 : 1
Thread-0 : 0
堵塞测试!!!

 */

synchronized方法安全线程

返回*

public class Demo2 {
    public static void main(String[] args) {
        Runnable t = new Ticket();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
        new Thread(t).start();
    }
    
    static class Ticket implements Runnable{
        int count = 10;
        @Override
        public void run() {
            while (true){
                if (sell()){
                    break;
                }
            }
        }
    
        private synchronized boolean sell() {
            if (count > 0){
                System.out.println(Thread.currentThread().getName()+" : "+ --count);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return false;
            }
            return true;
        }
    }
    
}

/*

Thread-0 : 9
Thread-0 : 8
Thread-0 : 7
Thread-0 : 6
Thread-0 : 5
Thread-0 : 4
Thread-3 : 3
Thread-3 : 2
Thread-1 : 1
Thread-1 : 0

* */

ReentrantLock安全线程

返回*

import java.util.concurrent.locks.ReentrantLock;

public class Demo3 {
    public static void main(String[] args) {
        Runnable lockTest = new LockTest();
        new Thread(lockTest).start();
        new Thread(lockTest).start();
        new Thread(lockTest).start();
        new Thread(lockTest).start();
    }
    
    static class LockTest implements Runnable{
    
        //显式锁
         static ReentrantLock l = new ReentrantLock(true);
        
        int count = 10;
        
        @Override
        public void run() {
            while (true){
                    l.lock();
                    if (sell()){
                        break;
                    }
                    if (count == 5){
                        test();
                    }
                l.unlock();
            }
            l.unlock();
            System.out.println("结束 : "+l.tryLock());
        }
    
        private void test() {
            System.out.println(l.toString());
            System.out.println(l.getHoldCount());
            System.out.println(l.getQueueLength());
        }
    
        private boolean sell() {
            if (count > 0){
                System.out.println(Thread.currentThread().getName()+" : "+ --count);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return false;
            }
            return true;
        }
        
    }
}

/*

Thread-0 : 9
Thread-3 : 8
Thread-2 : 7
Thread-1 : 6
Thread-0 : 5
java.util.concurrent.locks.ReentrantLock@47ee0a89[Locked by thread Thread-0]
1
3
Thread-3 : 4
Thread-2 : 3
Thread-1 : 2
Thread-0 : 1
Thread-3 : 0
结束 : true
结束 : false

*/

线程优先级

返回*

import javax.swing.*;
import java.awt.*;

public class PriorityBookTest extends JFrame {

    private Container c = getContentPane();
    private JProgressBar
            jp1 = new JProgressBar(),
            jp2 = new JProgressBar(),
            jp3 = new JProgressBar(),
            jp4 = new JProgressBar();
    private Thread
            threadA = null,
            threadB = null,
            threadC = null,
            threadD = null;

    public PriorityBookTest(){
        super("线程优先级");
        setBounds(300 , 230 ,100,150);
        setLayout(new FlowLayout());
        setVisible(true);

        threadA = new Thread(newThread(c , jp1));
        threadB = new Thread(newThread(c , jp2));
        threadC = new Thread(newThread(c , jp3));
        threadD = new Thread(newThread(c , jp4));
        setPriority("A" , 10 , threadA);
        setPriority("B" , 7 , threadB);
        setPriority("C" , 4 , threadC);
        setPriority("D" , 1 , threadD);
    }

    private static Thread newThread(Container c , JProgressBar jp){
        c.add(jp);
        jp.setStringPainted(true);
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                int count = 0 ;
                while (count <= 100){
                    jp.setValue(count++);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        return thread;
    }

    public static void setPriority(String threadName , int priority , Thread t){
        //设置进程优先级、名,启动
        t.setPriority(priority);
        t.setName(threadName);
        t.start();
    }

    public static void main(String[] args) {
        new PriorityBookTest();
    }
}

/*

执行结果 : 窗体展示 进度条

*/

缓存线程池

返回*

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//缓存线程池

public class Demo1 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        
        //执行任务
        service.execute(new Runnable() {
            @Override
            public void run() {
                 System.out.println(Thread.currentThread().getName()+" : 1");
            }
        });
    
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 2");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 3");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 4");
            }
        });
        
    }
}

/*

pool-1-thread-3 : 3
pool-1-thread-2 : 2
pool-1-thread-1 : 1
pool-1-thread-1 : 4

*/

定长线程池

返回*

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//定长线程池

public class Demo2 {
    
    public static void main(String[] args) {
        ExecutorService exception = Executors.newFixedThreadPool(2);
        
        exception.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 1");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        exception.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 2");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        exception.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 3");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    
        exception.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 4");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
    }
}

/*

pool-1-thread-1 : 1
pool-1-thread-2 : 2
pool-1-thread-2 : 3
pool-1-thread-1 : 4

*/

单线程线程池

返回*

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

//单线程线程池

public class Demo3 {
    public static void main(String[] args) {
        ExecutorService service = Executors.newSingleThreadExecutor();
        
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" : 3");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        
    }
}

/*

pool-1-thread-1 : 1
pool-1-thread-1 : 2
pool-1-thread-1 : 3

*/

周期性任务定长线程池

返回*

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

//周期性任务定长线程池

public class Demo4 {
    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(2);
    
        /**定时执行
         * 参数1. 线程
         * 参数2. 延时时长值
         * 参数3. 时长单位
         */
        service.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("延时2s , 执行的程序");
            }
        } , 2 , TimeUnit.SECONDS);
    
        /**周期执行
         * 参数1. 线程
         * 参数2. 延时时长值
         * 参数3. 周期间隔时长值
         * 参数4. 时长单位
         */
        service.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("延时3s 执行周期间隔2s 的循环程序");
            }
        } , 3 , 2 , TimeUnit.SECONDS);
        
        
    }
}

/*

延时2s , 执行的程序
延时3s 执行周期间隔2s 的循环程序
延时3s 执行周期间隔2s 的循环程序
延时3s 执行周期间隔2s 的循环程序
·····

*/
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值