线程常用操作方法

  多线程的主要操作方法都在Thread类中定义的。

1,线程的命名和取得

  多线程的运行状态是不确定的,那么在程序的开发之中为了可以获取到一些需要使用到的线程就只能依靠线程的名字来进行操作。所以线程的名字是一个至关重要的概念,这样在Thread类之中就提供有线程名称的处理。

    ①构造方法:public Thread(Runnable target,String name);

    ②设置名字:public final void setName(String name);

    ③取得名字:public final String getName();

  对于线程对象的获得是不可能只是依靠一个this来完成的,因为线程的状态不可控,但是有一点是明确的,所有的线程都要执行【run()方法】,那么这个时候可以考虑获取当前线程,在Thread类里面提供有

  ·范例:观察线程的命名操作

 class MyThread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread mt=new MyThread();
new Thread(mt,"线程A").start();
new Thread(mt).start();
new Thread(mt,"线程B").start();
new Thread(mt,"线程C").start();
new Thread(mt,"线程D").start();
}
}

  当开发者为线程设置名字的时候就是要设置的名称,而如果没有设置名字,则会自动生成一个不重复的名字。这种自动的属性命名主要是依靠了static属性完成的,在Thread类里面定义有如下操作:

 private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}

·范例:观察一个main线程程序

 public class Main {
public static void main(String[] args) {
MyThread mt=new MyThread();
new Thread(mt,"线程对象").start();
mt.run();
}
}
 main
线程对象

  通过此时的代码可以发现当使用了【mt.run()】直接在主方法里面之中调用线程类对象中的【run()】方法所获得的线程的名字为【main】所以可以得出一个结论:主方法也是一个线程。那么现在的问题来了,所有的线程都是在进程上的划分,那么进程在哪里?每当使用Java命令执行程序的时候就表示启动了一个JVM的进程,一台电脑上可以启动若干个JVM进程都会有各自的线程。

  在任何的开发之中,主线程可以创建若干个子线程。创建子线程的目的是可以将一些复杂逻辑或者比较耗时的逻辑交由子线程处理。

  ·范例:子线程的处理

 public class Main{
public static void main(String[] args) {
System.out.println("1,执行操作任务一");
new Thread(()->{
int temp=0;
for(int x=0;x<Integer.MAX_VALUE;x++){
temp += x;
}
System.out.println("2,执行操作任务二");
}).start();
System.out.println("3,执行操作任务三");
}
}

  主线程负责处理整体流程,而子线程负责处理耗时操作。

2,线程休眠

  如果说现在希望某个线程可以暂缓执行,那么就可以使用休眠的处理,在Thread中定义的休眠的方法如下:

    ·休眠:public static void sleep(long millis) throws InterruptedException;

    ·休眠:public static void sleep(long millis,int nanos) throws InterruptedException;

  在进行休眠的时候有可能会产生中断异常【InterruptedException】,中断异常属于Exception的子类,所以证明该异常必须进行处理。

  ·范例:观察休眠处理

 public class Main{
public static void main(String[] args) {
new Thread(()->{
for(int x=0;x<10;x++){
System.out.println(Thread.currentThread().getName()+"、x="+x);
try {
Thread.sleep(100);//暂缓执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"线程对象").start();
}
}

  ·范例:产生多个线程对象进行休眠处理休眠的主要特点是可以实现线程的自动唤醒,以继续进行后续的处理。但是需要注意的是,如果现在有多个线程对象,那么休眠也是有先后顺序的。

 public class Main{
public static void main(String[] args) {
Runnable run=()->{
for(int x=0;x<10;x++){
System.out.println(Thread.currentThread().getName()+"、x="+x);
try {
Thread.sleep(100);//暂缓执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
for(int num=0;num<5;num++){
new Thread(run,"线程对象-"+num).start();
}
}
}

  此时将产生五个线程对象,并且这五个线程对象执行的方法体是相同的。此时从程序执行的感觉上来讲好像若干个程序一起进行了休眠,而后一起进行了自动唤醒,但是实际上是有差别的。

3,线程中断

  在之前发现线程的休眠里面提供有一个中断异常,实际上就证明线程的休眠是可以打断的,而这种打断肯定是由其他线程完成的。

    ·判断线程是否被中断:public boolean isInterrupted();

    ·中断线程执行:public void interrupt();

  ·范例:观察线程的中断处理操作

 public class Main{
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
System.out.println("【需要睡觉保存体力】");
try{
Thread.sleep(10000);//预计准备休眠10s
}catch (InterruptedException e) {
System.out.println("【睡眠被打断】");
} System.out.println("【睡觉结束可以继续工作了】");
});
thread.start();
Thread.sleep(1000);
if(! thread.isInterrupted()){//该线程中断了吗
System.out.println("【有人来打扰我休息】");
thread.interrupt();//中断执行
}
}
}
 【需要睡觉保存体力】

 【有人来打扰我休息】

 【睡眠被打断】

 【睡觉结束可以继续工作了】

  所有正在执行的线程都是可以被中断的,中断线程必须进行异常处理。

4,线程强制运行

  所谓的线程的强制执行指的是当满足于某些条件之后,某一个线程对象将可以一直独占资源,一直到该线程的程序执行结束。

  ·范例:观察一个没有强制执行的程序

 public class Main{
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
for(int x=0;x<100;x++){
System.out.println(Thread.currentThread().getName()+"执行、x="+x);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"玩耍的线程");
thread.start();
for(int x=0;x<100;x++){
Thread.sleep(100);
System.out.println("【main线程】num="+x);
}
}
}

  ·强制执行:public final void join() throws InterruptException;这个时候主线程和子线程都在交替执行着,但是如果说现在你希望主线程独占执行。那么我们就可以使用【Thread类】中方法强制执行。

 public class Main{
public static void main(String[] args) throws InterruptedException {
Thread mainThread = Thread.currentThread();
Thread thread=new Thread(()->{//获得主线程
for(int x=0;x<100;x++){
if(x==3){
try {
mainThread.join();//主线程要优先执行
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"执行、x="+x);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"玩耍的线程");
thread.start();
for(int x=0;x<100;x++){
Thread.sleep(100);
System.out.println("【main线程】num="+x);
}
}
}

   在进行线程强制执行的时候一定要获取强制执行线程对象之后才可以执行join()调用。

5,线程礼让

  线程的礼让指的是现将资源让出去,让别的线程先执行。

    ·礼让:public static void yield();

  ·范例:使用礼让操作

 public class Main{
public static void main(String[] args) throws InterruptedException {
Thread mainThread = Thread.currentThread();
Thread thread=new Thread(()->{//获得主线程
for(int x=0;x<100;x++){
if(x%3==0){
Thread.yield();//线程礼让执行
System.out.println("礼让其他线程");
}
System.out.println(Thread.currentThread().getName()+"执行、x="+x);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"玩耍的线程");
thread.start();
for(int x=0;x<100;x++){
Thread.sleep(100);
System.out.println("【main线程】num="+x);
}
}
}

  礼让执行的时候每一次调用yield()方法都只会礼让一次当前的资源。

6,线程优先级

  从理论上来讲线程的优先级越高越有可能先执行(越有可能先抢占到资源)。在Thread类里面针对于优先级的操作提供有如下的两个方法:

    ·设置优先级:public final void setPriority(int newPriority);

    ·获取优先级:public final int getPriority()

  在定义优先级的时候都是通过int型的数字来完成的,而对于此数字的选择在Thread类里面就定义有三个常量:

    ①最高优先级:public static final int MAX_PRIORITY、10;

    ②中等优先级:public static final int NORM_PRIORITY、5;

    ③最低优先级:public static final int MIN_PRIORITY、1;

  ·范例:观察优先级

 public class Main{
public static void main(String[] args) throws InterruptedException {
Runnable run=()->{
for(int x=0;x<10;x++){
try{
Thread.sleep(1000);
} catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"执行");
}
};
Thread threadA=new Thread(run,"线程对象A");
Thread threadB=new Thread(run,"线程对象B");
Thread threadC=new Thread(run,"线程对象C"); threadA.setPriority(10);
threadB.setPriority(1);
threadC.setPriority(1); threadA.start();
threadB.start();
threadC.start();
}
}

  ·范例:主线程的优先级

 public class Main{
public static void main(String[] args) throws InterruptedException {
Thread mainThread=Thread.currentThread();
System.out.println(mainThread.getPriority());
}
}

  备注:优先级高的只是倾向于先执行,但是并不是一定优先执行。主线程属于中等优先级,而默认创建的线程也是中等优先级。

进阶Java编程(2)线程常用操作方法的更多相关文章

  1. 进阶Java编程(3)线程的同步与死锁

    线程的同步与死锁 1,同步问题引出 在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,对于当多个线程访问统一资源的时候如果处理不当就会产生数据的错误 ...

  2. 菜鸡的Java笔记 - java 线程常用操作方法

    线程常用操作方法        线程的命名操作,线程的休眠,线程的优先级            线程的所有操作方法几乎都在 Thread 类中定义好了            线程的命名和取得      ...

  3. JAVA基础语法:java编程规范和常用数据类型(转载)

    JAVA基础语法:java编程规范和常用数据类型 摘要 本文主要介绍了最基本的java程序规则,和常用数据类型,其中侧重说了数组的一些操作. 面向java编程 java是纯面向对象语言,所有的程序都要 ...

  4. 进阶Java编程(4)多线程深入话题

    多线程深入话题 1,优雅的停止线程 在多线程操作之中如果要启动多线程使用的肯定是Thread类中的start()方法,而如果对于多线程需要进行停止处理,Thread类原本提供有stop()方法,但是这 ...

  5. 进阶Java编程(5)基础类库

    Java基础类库 1,StringBuffer类 String类是在所有项目开发之中一定会使用到的一个功能类,并且这个类拥有如下的特点: ①每一个字符串的常量都属于一个String类的匿名对象,并且不 ...

  6. 进阶Java编程(9)反射与类操作

    1,反射获取类结构信息 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作,任何一个类的基本组成结构:父类(父接口).包.属性.方法(构造方法与普通方法). ...

  7. 进阶Java编程(6)正则表达式

    正则表达式 通过之前一系列的分析可以发现,String是一个非常万能的类型,因为String不仅仅可以支持有各种字符串的处理操作,也支持有向各个数据类型的转换功能,所以在项目的开发之中,只要用户输入的 ...

  8. 进阶Java编程(1)多线程编程

    Java多线程编程 1,进程与线程 在Java语言里面最大的特点是支持多线程的开发(也是为数不多支持多线程的编程语言Golang.Clojure方言.Elixir),所以在整个的Java技术学习里面, ...

  9. java中 File文件常用操作方法的汇总

    一.IO流: 1.全称为:Input Output---------输入输出流. 输入:将文件读到内存中. 输出:将文件从内存中输出到其他地方. 2.IO技术的作用: 主要是解决设备与设备之间的数据传 ...

随机推荐

  1. RHEL 6.10系统安装配置图解教程

    EL 6.10系统安装配置图解教程(rhel-server-6.5) 截止目前RHEL 6.x最新版本为RHEL 6.10,下面介绍RHEL 6.10的具体安装配置过程,需要的朋友可以参考下 一.安装 ...

  2. [Java]给指定时间加上十秒

    package com.testEmp; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util. ...

  3. PHP学习之PHP代码的优化

    if代码块的优化 if(1===$orderState){     $status='success'; }else{     $status='error'; } return $status; 简 ...

  4. 对String的内存解析

    @Test public void stringTest(){ /* * str1和str2地址指向字符串常量池 * 解析: str1 在字符串常量池中创建出java 地址例如为:0x456 * st ...

  5. Oracle事务、视图、序列

    回顾什么是事务? 一个不可分割的子操作形成一个整体,该整体要么全部执行成功,要么全部执行失败.例如:转帐 回顾为什么要用事务? 如果不用事务的话,为转帐为例,可能出现一个用户钱增加了,另一个用户钱不变 ...

  6. eclipse下生成Java类图和时序图,生成UML图

    1.安装和使用AmaterasUML 安装AmaterasUML前,需要先安装GEF采用eclipse在线安装方式安装就好.eclipse在线安装GEF的地址:http://download.ecli ...

  7. 012-数据结构-树形结构-哈希树[hashtree]、字典树[trietree]、后缀树

    一.哈希树概述 1.1..其他树背景 二叉排序树,平衡二叉树,红黑树等二叉排序树.在大数据量时树高很深,我们不断向下找寻值时会比较很多次.二叉排序树自身是有顺序结构的,每个结点除最小结点和最大结点外都 ...

  8. Spring+Ibatis开发

    Spring+Ibatis开发:1.首先回忆Spring+Hibernate开发:那么时候我们是先加入的Spring,然后在加入Hibernate支持包的,而此时我们Spring+Ibatis开发,原 ...

  9. 跨平台编程相关技术资料及笔记.md

    目录 跨平台编程技术选型 ## 需求 最终选定的技术方案:uni-app 混合或跨平台编程相关资料 ## uni-app 官网 相关资料 个人笔记 个人经验 ## taro 官网 相关资料 ## Ch ...

  10. 分布式存储ceph--osd故障硬盘更换(6)

    正常状态: