命名
对于线程对象的获得是不可能只是靠一个this来完成的,因为线程的 状态不可控,但是所有的线程必须要执行run方法.
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,"线程").start();//设置了名字
new Thread(mt).start();//没有设置名字
new Thread(mt).start();//没有设置名字
new Thread(mt,"线程b").start();//设置了线程的名字
mt.run();
//main main的出现顺序并不一定,说明了main方法也是一个线程
//输出
//线程
//Thread-0
//Thread-1
//线程b
}
}
//当开发者为线程的设置名字的时候就是用了设置的名字,而如果没有设置名字,则会用自动生成一个不重复的名字,这种自动属性命名主要是依靠了static属性完成的,在Thread类里面定义有如下操作
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
通过重载构造方法,如果没有传入名字,就自动生成命名
每当使用java命令执行程序的时候就表示启动了一个jvm的进程,一台电脑上可以启动若干个jvm的进程。在任何的开发之中,主线程可以创建多个子线程。创建子线程的目的是可以将一些复杂的逻辑交给子线程处理。
主线程负责处理整体流程,而子线程负责处理耗时操作
线程的休眠
如果说希望某一个线程可以暂缓执行,那么就可以使用休眠的处理,在Thread类当中定义的休眠的方法,会产生一个中断异常,InterruptedException,中断异常属于Exception的子类,所以必须进行处理
休眠的主要特点是可以自动实现线程的唤醒,进行后续的处理。
休眠不影响其他线程的程序运行
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
线程的中断
public class Main {
public static void main(String[] args) {
Thread thread=new Thread(()->{
try {
Thread.sleep(5000);
System.out.println("过了5秒了");
} catch (InterruptedException e) {
System.out.println("出现了异常,被打断了");
}
});
thread.start();
/////判断线程是否被中断
if(!thread.isInterrupted()){//返回true线程被终端,false没被中断
System.out.println("你的执行将会被我中断");
thread.interrupt();//中断运行
}
System.out.println("程序结尾");
//输出程序结尾 出现了异常,被打断了
}
}
所有在执行的线程都是可以中断的,中断线程必须进行异常处理
线程的强制运行
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread mainThread=Thread.currentThread();//获得主线程
Thread thread=new Thread(()->{
for(int i=0;i<10000;i++){
System.out.println("子线程");
}
});
thread.start();
thread.join();
//判断线程是否被中断
for(int i=0;i<10000;i++){
System.out.println("主main线程");
}
}
}
先输出子字线程再输出主线程
以下代码可以实现先执行完子线程之后再执行主线程
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread mainThread=Thread.currentThread();//获得主线程
Thread thread=new Thread(()->{
for(int i=0;i<100000;i++){
System.out.println("线程1");
}
});
Thread thread2=new Thread(()->{
for(int i=0;i<100000;i++){
System.out.println("线程2");
}
});
thread.start();
thread2.start();
thread.join();
thread2.join();
System.out.println("结尾");
}
}
线程礼让
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread mainThread=Thread.currentThread();//获得主线程
Thread thread=new Thread(()->{
for(int i=0;i<100000;i++){
if (i%3==0){
System.out.println("我下面要让他执行了");
// Thread.yield();//线程礼让执行
}
System.out.println("礼让的线程"+i);
}
});
Thread thread2=new Thread(()->{
for(int i=0;i<100000;i++){
System.out.println("霸道的线程"+i);
}
});
thread.start();
thread2.start();
thread.join();
thread2.join();
System.out.println("结尾");
}
}
礼让执行的时候每一次调用yield()方法都只会礼让一次当前的资源
线程的优先级
再java的线程操作中,所有的线程,再运行前都会保持就绪状态,此时哪个线程的优先级高,哪个线程就更有可能会被先执行
在对优先级定义的时候,通常都是通过int型的数字来完成的,而对于此数字的常量在Thread类里面就定义完成了
- 最高优先级 public static final int MAX_PRIOTY 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++){
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(Thread.MAX_PRIORITY);//设置优先级
threadA.getPriority();//获取优先级返回int
threadB.setPriority(Thread.NORM_PRIORITY);
threadA.start();
threadB.start();
threadC.start();
}
}
//如上代码A会更快的执行完
可以用Thread.currentThread();获得主线程的优先级输出之后发现是5和普通线程是一样的