进阶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技术的作用: 主要是解决设备与设备之间的数据传 ...
随机推荐
- Nginx数据结构之内存池
基本结构 1. ngx_pool_t struct ngx_pool_s { ngx_pool_data_t d; size_t max; ngx_pool_t *current; ngx_chain ...
- 微信小程序 保存图片
微信小程序 保存图片 注: 此处使用的是小程序 wepy框架, 原生或其他的请注意转换写法 <div class="handle"> <button class= ...
- 汽车辐射监测系统-Qt开发[转]发
功能介绍: 利用在路边的两个探测器,探测汽车的辐射剂量,通过电子板进行数据采集,并串口传输到计算机,实时显示.可以保存采集数据,进行独立显示. 开发环境: VS2008,Qt4.7, QWT 6.0. ...
- shapefile 输出的地理处理注意事项
多年来,ESRI 为存储地理信息开发了三种主要数据格式 - coverage 格式.shapefile 格式及地理数据库格式.其中,所开发的 Shapefile 为存储地理及属性信息提供了一种简单的非 ...
- linux如何离线加载docker镜像?
1. 在已经部署了镜像的机器上获取镜像 1.1 获取镜像名 docker images 1.2 打包选中对应的镜像 docker save <image_name> -o <imag ...
- MySQL使用空事务解决slave从库errant问题
MySQL集群一般部署为主从架构,主库专门用于写入数据,从库用于读数据. 异常情况下,在从库上写入数据,就会出现主从数据不一致问题,称为errant. 如果从库上的这些数据主库上已经有了,或者主库不需 ...
- Java之加密算法
加密算法主要分为对称加密.非对称加密.Hash加密. 一.何为对称加密? 对称加密是指对称密码编码技术,它的特点是文件加密和解密使用相同的密钥加密. 对称机密的密钥一般小于256bit.因为就密钥而言 ...
- Button加在UITableViewHeaderFooterView的self.contentView上导致不能响应点击
你有没有遇到过Button加在UITableViewHeaderFooterView的self.contentView上导致不能响应点击的情况,下面记录一下我遇到的原因和解决方法: 代码如下: - ( ...
- Spring Boot Mybatis简单使用
Spring Boot Mybatis简单使用 步骤说明 build.gradle:依赖添加 application.properties:配置添加 代码编写 测试 build.gradle:依赖添加 ...
- mysql主主、mysql-proxy读写分离、keepalived高可用完美组合
配置mysql主主复制 服务器A:172.16.100.9 服务器B:172.16.100.10 首先在服务器A和服务器B上各安装好单机版mysql5.7,安装好后,再继续下面的操作. 在服务器A和服 ...