进阶Java编程(2)线程常用操作方法
线程常用操作方法
多线程的主要操作方法都在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)线程常用操作方法的更多相关文章
- 进阶Java编程(3)线程的同步与死锁
线程的同步与死锁 1,同步问题引出 在多线程的处理之中,可以利用Runnable描述多个线程操作的资源,而Thread描述每一个线程对象,对于当多个线程访问统一资源的时候如果处理不当就会产生数据的错误 ...
- 菜鸡的Java笔记 - java 线程常用操作方法
线程常用操作方法 线程的命名操作,线程的休眠,线程的优先级 线程的所有操作方法几乎都在 Thread 类中定义好了 线程的命名和取得 ...
- JAVA基础语法:java编程规范和常用数据类型(转载)
JAVA基础语法:java编程规范和常用数据类型 摘要 本文主要介绍了最基本的java程序规则,和常用数据类型,其中侧重说了数组的一些操作. 面向java编程 java是纯面向对象语言,所有的程序都要 ...
- 进阶Java编程(4)多线程深入话题
多线程深入话题 1,优雅的停止线程 在多线程操作之中如果要启动多线程使用的肯定是Thread类中的start()方法,而如果对于多线程需要进行停止处理,Thread类原本提供有stop()方法,但是这 ...
- 进阶Java编程(5)基础类库
Java基础类库 1,StringBuffer类 String类是在所有项目开发之中一定会使用到的一个功能类,并且这个类拥有如下的特点: ①每一个字符串的常量都属于一个String类的匿名对象,并且不 ...
- 进阶Java编程(9)反射与类操作
1,反射获取类结构信息 在反射机制的处理过程之中不仅仅只是一个实例化对象的处理操作,更多的情况下还有类的组成结构操作,任何一个类的基本组成结构:父类(父接口).包.属性.方法(构造方法与普通方法). ...
- 进阶Java编程(6)正则表达式
正则表达式 通过之前一系列的分析可以发现,String是一个非常万能的类型,因为String不仅仅可以支持有各种字符串的处理操作,也支持有向各个数据类型的转换功能,所以在项目的开发之中,只要用户输入的 ...
- 进阶Java编程(1)多线程编程
Java多线程编程 1,进程与线程 在Java语言里面最大的特点是支持多线程的开发(也是为数不多支持多线程的编程语言Golang.Clojure方言.Elixir),所以在整个的Java技术学习里面, ...
- java中 File文件常用操作方法的汇总
一.IO流: 1.全称为:Input Output---------输入输出流. 输入:将文件读到内存中. 输出:将文件从内存中输出到其他地方. 2.IO技术的作用: 主要是解决设备与设备之间的数据传 ...
随机推荐
- Linux设备驱动程序 之 获取当前时间
墙上时间 内核一般通过jiffies来获取当前时间,该数值表示的是最近一次系统启动到当前的时间间隔,它和设备驱动程序无关,因为它的声明期只限于系统的运行期:但是驱动程序可以用jiffies来计算不同事 ...
- phpstorm配置了git后Terminal 不能使用显示:git' 不是内部或外部命令,也不是可运行的程序
问题:在phpstorm上配置好git后,将代码拉了下来 ,但是命令行无法使用显示如图 解决方法:①找到安装git的位置,然后在该目录的子目录下分别找到git-core.bin 两个目录,我的安装在了 ...
- MySQL 中<=>用法(长知识)
https://www.runoob.com/mysql/mysql-operator.html MySQL 运算符 本章节我们主要介绍 MySQL 的运算符及运算符的优先级. MySQL 主要有以下 ...
- 【JDBC】使用Spring提供的JDBCTemplate通过Statement向MySql数据库插入千万条数据,耗时4m55s,使用insert语句批量插入方式二
这回依然是使用 insert批量插入这种方式 insert into emp(name,age,cdate) values ('A' , 20, '2019-10-13 00:00:00'), ('B ...
- 记录学习Linux过程
第一步fdisk-l 出错 Permission denied? ubuntu@VM-0-6-ubuntu:~$ fdisk -l fdisk: cannot open /dev/vda: Permi ...
- Go语言fmt.Printf使用指南(占位符总结)
本文整理了Go语言的标准输出流(fmt.Printf)在打印到屏幕时的格式化输出操作. 在这里按照占位符将被替换的变量类型划分,更方便查询和记忆. 总结 1.1 General(通用占位符) 占位符 ...
- leetcode218 天际线问题
来自leetcode题解:扫描线法AlgsCG class Solution { public: vector<vector<int>> getSkyline(vector&l ...
- 加载自定义目录下的springmvc.xml配置文件
在默认情况下:springmvc框架的配置文件必须叫<servlet-name>-servlet.xml 且必须放在/WEB-INF/目录下,我们可以在web.xml文件中,为Dispat ...
- UML分类
类型 静态图 行为图 用例图 交互图 ...
- Event事件与协程
1.Event事件 Event事件的作用: - 用来控制线程的执行. - 由一些线程去控制另一些线程. 2.进程池与线程池 1)什么是进程池与线程池? 进程池与线程池是用来控制当前程序允许创建(进程/ ...