Java线程笔记

线程不拥有系统资源,线程拥有自己的堆栈、计数器等,但是它是与进程的其他线程共享的资源,非自己拥有。
线程是独立运行的,并不知道是否还有其他线程存在,但可以编程通过共享方式进行通信。其调度方式为优先级+抢占。
由于进程不需要分配独立的进程空间,其效率更高。
进程的应用实例:
1、word的输入和输入时检查
2、浏览器同时下载多个图片
3、变下载边播放、展示

进程的状态:
newBorn:被创建但是未开始执行,可通过start方法启动,产生这个进程需要的系统资源。通过调用run方法进入Runnable状态
Runnable状态:线程处于就绪状态,在队列中根据优先级和先到先得等待处理器资源
Running状态:正在运行中,在run方法执行完成后退出运行状态。除非进程运行中主动放弃或者被更高优先级进程抢占,否则会一直运行下去。
Blocked状态:阻塞,进程处于这个状态无法进入就绪队列,需要被其他时间唤醒。—小心 可能进入死锁
Dead状态:执行完毕或者被强行中断。死了就是死了,不能通过start方法再运行。stop方法课强行停止,但是已经不被推荐使用。

在这里插入图片描述
进程从running退出的条件和方法
1、主动释放或者被更高优先级抢占
2、sleep方法和yield方法,yield只给相同优先级的执行机会。注:sleep结束后进入的是runnable状态 不是running
3、wait等待需要的变量的方法
4、输入输出发生线程阻塞
5、suspend方法 已经不再推荐使用

/**
 * 使用继承使用线程的方式
 * 1、写一个类继承Thread类,然后必须重写run方法
 * 2、主线程中新建对象,然后run方法即可
 */
class CreatThread extends Thread { // Thread 属于lang包 无需单独引入

    // 必须写run方法覆盖父类
    public void run() {
        System.out.println();
        System.out.println("子线程开始:" + this);
        System.out.println(this.getName()); //getName方法获取线程名字
        for (int i = 0; i < 4; i++) {
            System.out.println(this + "." + i);
        }
    }
}

public class ThreadTest {
    public static void main(String[] args) {
        CreatThread thread1 = new CreatThread();
        CreatThread thread2 = new CreatThread();
        thread1.start();
        thread2.start();
        /**
         * 子线程开始:Thread[Thread-1,5,main]
         * 子线程开始:Thread[Thread-0,5,main]
         * Thread-0
         * Thread[Thread-0,5,main].0
         * Thread-1
         * Thread[Thread-0,5,main].1
         * Thread[Thread-1,5,main].0
         * Thread[Thread-0,5,main].2
         * Thread[Thread-0,5,main].3
         * Thread[Thread-1,5,main].1
         * Thread[Thread-1,5,main].2
         * Thread[Thread-1,5,main].3
         */
    }
}

注:Thread.currentThread是静态方法,可返回当前正在执行的进程(可现实main进程)
getPriority和setPriority方法可获取和设置优先级

由于stop方法不再被推荐使用,那么如何实现进程的停止呢?

//只用一次时候 每次都要想类名很烦 所以需要匿名类
class X extends Thread{
private boolean running=false;
public void run(){
while(running){
do something
}
}

public void start(){
running=true;
super.start;
}

public void halt(){
running=false;
}

由于1、继承方式创建线程时,多个线程直接无法共享实例变量! 2、java只能单继承 而有些类如Frame或者Applet 必须被拓展
所以需要runnable接口创建进程

Runnable接口实现线程

public class ThreadTestByImplements implements Runnable{
    /**
     * implements实现进程的方法
     * 1、继承Runnable接口
     * 2、必须重写run方法
     * 3、在构造器或者方法中,通过Thread name = new Thread(this)变为线程,然后name.start()的方式自动调用run方法
     * 注,new Thread(this,"名字")可为线程指定名字
     * 4、由于最好设置停止机制,所以写代码的时候可以使用下面这样的模板。
     */
    private Thread threadName=null;
    public void start(){
        if(threadName==null){
            threadName=new Thread(this);
            threadName.start();
        }
    }

    public void stop(){
        threadName=null;
    }

    public run(){
        //可通过currentThread获取进程名 然后判断名字相等
        //do 具体逻辑
    }


    public static void main(String[] args) {
        ThreadTestByImplements a = new ThreadTestByImplements();
        a.start();
        a.run();
        a.stop();
    }


}

实例:没秒输出一次时间,由于这个例子不能阻塞其他运行 因此最好使用进程来写

import java.util.Date;

public class ThreadTestByImplements implements Runnable{
    private Thread clocker = null;
    //构造方法中开启线程
    public ThreadTestByImplements(){
        clocker = new Thread(this);
        clocker.start(); //需要手动写start方法 是和继承的不同之处
    }
    //必须run方法,具体逻辑写这里
    public void run(){
        while(true){
            Date now = new Date();
            System.out.println(now);
            try{
                clocker.sleep(1000);//也可直接Thread.sleep 这个是让当前运行的进程睡眠 实际就是clocker
            }catch(InterruptedException e){

            }
        }

    }

    public static void main(String[] args) {
        ThreadTestByImplements aBC = new ThreadTestByImplements();
    }



}

Callable方法创建进程 书写的不好 暂不看

Daemon Thread ----后台进程、守护进程

JVM垃圾回收就是典型的后台线程
特征:如果所有的前台进程都死亡,后台进程也会死亡
通过setDaemon(true)方法指定为后台进程(必须再start方法之前调用)

线程安全—线程同步

问题引入:比如当同时两个人对一个账户进行存、取操作,当线程刚好在读取到余额准备扣钱的时候,或者判断余额是否足够的时候,进程切换了。那么会导致错误的结果

方法1

为此 使用 synchronized对线程加锁
使用方法1:方法申明为synchronized
使用方法2:synchronized(要锁定的参数变量){ 代码块}

管程(互斥锁)、Lock(同步锁)

线程通信

1、当使用Syn时候wait方法 等待其他线程notify()或者notifyAll() 然后才能继续
2、当使用Lock时,不能使用上面的方法 要用Condition控制
3、java5引入的阻塞队列

线程组

使用Tread的构造器实现 此处不赘述

线程池

系统启动一个新线程的成本是比较高的,因为它设计和操作系统的交互,当需要很多生存期很短暂的线程的时候,这种情况可以使用线程池,先预先创新大量空线程等待使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值