资讯专栏INFORMATION COLUMN

java 多线程

IamDLY / 3372人阅读

摘要:总结创建线程,方法运行线程。创建线程使用继承类实现创建线程文档该类必须重写方法。为新线程的入口点。中断线程它表示一个线程被中断,会抛出错误。

java多线程

关于内存

每个线程会有自己的线程栈,即,变量不能共享,只能传值拷贝
每个线程new出的对象全都保存在堆中,全部共享

线程的生命周期

线程具有5种状态,即新建,就绪,运行,阻塞,死亡。
新建,当new出来一个线程以后,jvm为其分配内存空间,并初始化成员变量的值
就绪,当线程调用了strat()方法的时候,线程就绪,会为其创建方法调用栈和程序计数器。

方法调用栈 即,记录方法调用的次数
程序计数器 存放下一条单元指令的地方

运行;就绪状态获得cpu,开始执行run()方法
阻塞:例如进入I/O操作

新建,就绪

使用new关键字创建一个线程以后,该线程处于新建状态,和其他java线程一样,仅仅由java虚拟机为其分配内存,初始化变量成员的值。

运行和阻塞 线程调度

桌面和服务器使用抢占式调度策略,小型设备使用协作式调度策略,

线程阻塞

线程使用sleep()方法主动放弃所占用的处理器资源。
线程调用阻塞式I/O方法,方法被返回前,阻塞
线程等待通知
线程调用suspend()挂起

解除阻塞

依依对应即可

线程优先级

普通5,低1,高10
默认是5

关于start和run

start创建一个线程,由于是时间片运行的,所以需要run方法进行运行。
总结
start创建线程,run方法运行线程。

创建线程 使用Thread继承类实现创建线程

文档 https://docs.oracle.com/javas...
该类必须重写run方法。为新线程的入口点。
必须调用start()方法才能运行。

本质上是Runnable接口的一种实现
package demo2;

public class test {
    public static void main(String[] args) {
        // 创建一个线程
        ThreadDemo run1 = new ThreadDemo();
        run1.start();// 启动线程
        // 在运行线程以后,会不定时的jvm调用run方法,进行运行
    }
}
package demo2;

public class ThreadDemo extends Thread{
    public ThreadDemo() {
        System.out.println("hello world");
    }
    
    public void run() {
        System.out.println("线程进入");
        for(int i = 0; i > 10; i++) {
            System.out.println("输出内容");
        }
        System.out.println("线程执行完毕");
    }
}

事实上父类的start方法也可以重写

package demo2;

public class ThreadDemo extends Thread{
    public ThreadDemo() {
        System.out.println("hello world");
    }
    
    public void run() {
        System.out.println("线程进入");
        for(int i = 0; i > 10; i++) {
            System.out.println("输出内容");
        }
        System.out.println("线程执行完毕");
    }
    
    public void start() {
        System.out.println("启动线程");
        this.run();
    }
}

然后测试类

package demo2;

public class test {
    public static void main(String[] args) {
        // 创建一个线程
        ThreadDemo run1 = new ThreadDemo();
        run1.start();// 启动线程
    }
}
Thread方法 public final void setDaemon(boolean on)

用于标记守护线程和用户线程
用户线程,平常创建的普通线程
守护线程,服务于用户线程,不需要上层调用,例如gc垃圾回收为一个明显的守护线程,mysql中也有执行定时任务的线程。

中断线程

它表示一个线程被中断,会抛出错误。

使用Runnable接口

文档https://docs.oracle.com/javas...
属于java.lang包内的,为自动默认加载的
该接口具有一个run方法,run方法为程序的入口
必须通过Thread类的构造方法实现启动线程

package demo2;

public class test {
    public static void main(String[] args) {
        // 创建一个线程
        demoRunnable r1 = new demoRunnable();
        // 使用Thread类的构造方法传入线程,并起名,然后运行
        new Thread(r1, "name").start();// 创建完成线程以后,调用start启动线程
    }
}
package demo2;

public class demoRunnable implements Runnable{
    private int i;

    // 下方的为运行的线程
    @Override
    public void run() {
        for(int i = 0; i < 100; i++) {
            System.out.println("运行线程 " + i);
        }
    }
}
通过Callable和Future来创建线程

使用Callable创建接口的实现类
接口源码如下

@FunctionalInterface
public interface Callable {
    V call() throws Exception;
}

实现了一个泛型,该并且返回该类型,需要实现call方法。使用包装对象

关于包装类型,即,将不是对象的内容包装成为对象,为包装类型,实现了对象的类型,为一个类

先实现Callable接口,其中的call类为程序的子线程的执行体

package demo2;

import java.util.concurrent.Callable;

public class CallableDemo implements Callable{
    @Override
    public Integer call() throws Exception {
        System.out.println("开始运行一个线程");
        for(int i = 1, i < 10; i++) {
            System.out.println("运行中");
        }
        // 阻塞该线程
        Thread.sleep(200);
        return 1;    // 返回线程的值
    }
}

接着创建Future对象,将用于启动子线程

package demo2;

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

public class test {
    public static void main(String[] args) {
        // 先创建实例
        CallableDemo ctt = new CallableDemo();
        FutureTask ft = new FutureTask<>(ctt);    // 该方法为了获取返回值而设定    
        new Thread(ft, "返回结果的值").start();
        try {
            System.out.println(ft.get());
        } catch (InterruptedException | ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
package demo2;

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

public class CallableDemo implements Callable{
    @Override
    public Integer call() throws Exception {
        System.out.println("开始运行一个线程");
        for(int i = 1; i < 10; i++) {
            System.out.println("运行中");
        }
        return 1;    // 返回线程的值
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/72279.html

相关文章

  • Java线程学习(一)Java线程入门

    摘要:最近听很多面试的小伙伴说,网上往往是一篇一篇的多线程的文章,除了书籍没有什么学习多线程的一系列文章。将此线程标记为线程或用户线程。 最近听很多面试的小伙伴说,网上往往是一篇一篇的Java多线程的文章,除了书籍没有什么学习多线程的一系列文章。但是仅仅凭借一两篇文章很难对多线程有系统的学习,而且面试的时候多线程这方面的知识往往也是考察的重点,所以考虑之下决定写一系列关于Java多线程的文章...

    Donne 评论0 收藏0
  • Java线程专题一:并发所面临的问题

    摘要:但是并不是什么多线程就可以随便用,有的时候多线程反而会造成系统的负担,而且多线程还会造成其他的数据问题,下面就来介绍一下多线程面临的问题。下面这张图是多线程运行时候的情况,我们发现上下文切换的次数暴增。 并发的概念: 在Java中是支持多线程的,多线程在有的时候可以大提高程序的速度,比如你的程序中有两个完全不同的功能操作,你可以让两个不同的线程去各自执行这两个操作,互不影响,不需要执行...

    madthumb 评论0 收藏0
  • Java线程可以分组,还能这样玩!

    摘要:如图所示,带有的所有线程构造方法都可以定义线程组的。线程组还能统一设置组内所有线程的最高优先级,线程单独设置的优先级不会高于线程组设置的最大优先级。 前面的文章,栈长和大家分享过多线程创建的3种方式《实现 Java 多线程的 3 种方式》。 但如果线程很多的情况下,你知道如何对它们进行分组吗? 和 Dubbo 的服务分组一样,Java 可以对相同性质的线程进行分组。 来看下线程类 Th...

    biaoxiaoduan 评论0 收藏0
  • JAVA 线程和并发基础

    摘要:线程可以被称为轻量级进程。一个守护线程是在后台执行并且不会阻止终止的线程。其他的线程状态还有,和。上下文切换是多任务操作系统和多线程环境的基本特征。在的线程中并没有可供任何对象使用的锁和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻译:并发编程网 - 郑旭东 校对:方腾飞 多...

    vboy1010 评论0 收藏0
  • Java线程学习(七)并发编程中一些问题

    摘要:相比与其他操作系统包括其他类系统有很多的优点,其中有一项就是,其上下文切换和模式切换的时间消耗非常少。因为多线程竞争锁时会引起上下文切换。减少线程的使用。很多编程语言中都有协程。所以如何避免死锁的产生,在我们使用并发编程时至关重要。 系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)syn...

    dingding199389 评论0 收藏0
  • 学习Java线程的一些总结

    摘要:多线程环境下的一些问题安全性问题在没有正确同步的情况下,多线程环境下程序可能得出错误的结果。一些相关概念竞争条件多线程的环境下,程序执行的结果取决于线程交替执行的方式。而线程的交替操作顺序是不可预测的,如此程序执行的结果也是不可预测的。 入口 Java多线程的应用复杂性之如jvm有限的几个内存方面的操作和规范,就像无数纷繁复杂的应用逻辑建立在有限的指令集上。 如何写出线程安全的程序,有...

    coolpail 评论0 收藏0

发表评论

0条评论

IamDLY

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<