您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
javase第三季学习笔记-线程的操作方法
发布时间:2017-08-10 16:07:59编辑:雪饮阅读()
线程的操作方法
Thread(Runnable target)
分配新的 Thread 对象。
Thread(Runnable target, String name)
分配新的 Thread 对象。
Thread(String name)
分配新的 Thread 对象。
static Thread currentThread()
返回对当前正在执行的线程对象的引用。
long getId()
返回该线程的标识符。
void setName(String name)
改变线程名称,使之与参数 name 相同。
boolean isAlive()
测试线程是否处于活动状态。
代码示例:
package com.vince.thread;
public class ThreadDemo {
public static void main(String[] args) {
//主线程名称输出(主线程名称为main)
System.out.println("获取当前线程名称:"+Thread.currentThread().getName());
Thread t1=new Thread(new MyThread());
//输出线程标识符
System.out.println(t1.getId());
t1.start();
//检查某线程是否在活动状态,该语句若在start语句之前则返回false,因为start还未执行
System.out.println("t1线程是否在活动状态:"+t1.isAlive());
Thread t2=new Thread(new MyThread());
System.out.println("t2线程是否在活动状态:"+t2.isAlive());
t2.start();
//自定义线程的线程名称也可以自定义
Thread t3=new Thread(new MyThread(),"自定义线程3");
t3.start();
//自定义线程名称的第二种方式
Thread t4=new Thread(new MyThread());
t4.setName("自定义线程4");
t4.start();
}
}
class MyThread implements Runnable{
public void run(){
//子线程名称默认形如"Thread-0",其中0为序号
System.out.println("获取当前线程名称:"+Thread.currentThread().getName());
}
}
static void sleep(long millis)
休眠指定的毫后继续执行
static void sleep(long millis, int nanos)
休眠指定毫秒和纳秒之后继续执行。
void join()
等待该线程终止。
void join(long millis)
等待该线程终止的时间最长为 millis 毫秒。
void join(long millis, int nanos)
等待该线程终止的时间最长毫秒 纳秒。
多线程开启后,多线程是交替运行的,一会儿这个,一会儿那个的。
sleep会将当前线程(设为线程1)某语句(设当前执行为a)暂停,例如暂停1秒,则会将cpu执行时间(假设是10秒)减去1秒后的时间交出去,然后其它线程继续抢剩下的9秒。
如果遇到另外一个线程(设为线程2)也执行到了a处,发现a处已经被一个线程暂停,那么线程2需要等待。等线程1暂停时间已经到达后,线程1又会重新去抢cpu执行时间。
sleep示例代码:
package com.vince.thread;
public class ThreadDemo2 {
public static void main(String[] args) {
Thread t1=new Thread(new MyThread2());
t1.start();
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"-"+i);
//每次休眠1000毫秒,即每1秒打印一次
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
示例代码:
package com.vince.thread;
public class ThreadDemo3 {
public static void main(String[] args) {
MyThread3 my=new MyThread3();
Thread t1=new Thread(my);
t1.start();
for (int i = 0; i < 10; i++) {
if(i==5){
try {
t1.join();//等待线程终止,这里的意思是,如果i=5则一直等待t1线程执行完毕,然后此处语句才可以继续向下执行
System.out.println(i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread3 implements Runnable{
public void run(){
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"-"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
void interrupt()
中断线程。
static boolean interrupted()
测试当前线程是否已经中断。
void setPriority(int newPriority)
更改线程的优先级。
int getPriority()
返回线程的优先级。
static int MAX_PRIORITY
线程可以具有的最高优先级。
static int MIN_PRIORITY
线程可以具有的最低优先级。
static int NORM_PRIORITY
分配给线程的默认优先级。
示例代码:给线程添加中断状态
package com.vince.thread;
public class ThreadDemo4 {
public static void main(String[] args) {
MyThread4 my=new MyThread4();
Thread t1=new Thread(my);
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println("main-"+i);
if(i==5){
//中断线程,api上这样解释,实际上只是设置了一个中断标记(中断状态为true)
//线程只能自己中断自己,要想中断它,只能给它通知,然后它自己去中断
t1.interrupt();
}
try {
//当线程被标记为终止状态时,调用sleep(不仅仅sleep还有一些方法,详见api)方法则会抛出异常,但该线程要运行的任务还是会继续下去的
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
class MyThread4 implements Runnable{
public void run(){
for (int i = 0; i <10; i++) {
System.out.println(Thread.currentThread().getName()+"-"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
}
示例代码:线程内通过Thread.interrupted()获取当前线程的中断标记状态并根据该状态来处理业务逻辑。
package com.vince.thread;
public class ThreadDemo4 {
public static void main(String[] args) {
MyThread4 my=new MyThread4();
Thread t1=new Thread(my);
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println("main-"+i);
if(i==5){
t1.interrupt();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread4 implements Runnable{
public void run(){
int i=0;
//Thread.interrupted()函数可以获取线程是否被标记为中断
//!Thread.interrupted()表示线程没有被中断
while (!Thread.interrupted()) {
System.out.println(Thread.currentThread().getName()+"-"+i);
i++;
try {
/*
虽然通过!Thread.interrupted()这个规避了线程中断,但由于多线程的原因,该线程可能会随时随地被标记为中断.
为什么会随时被中断呢?我们看看这样一个场景:
当cpi时间片被当前线程抢到后,由于cpu时间片比较少,所以该线程代码执行到上面i++处就时间耗尽,该线程暂时搁置了。等下一次cpu时间片又被分配来的时候,这次未必本线程抢到了
有可能是主线程main抢到了,或者其它线程抢到了,这里以主线程为例,主线程中有一个标记本线程中断的方法,如果刚好cpu时间片足以执行到标记本线程中断方法完毕,那么笨线程则会被中断。
然后主线程接受的cpu时间段耗尽后,又被搁置,再等下一次cpu时间段分配来的时候,有可能是本线程抢到了,本线程继续执行i++后面的程序直到Thread.sleep(1000)就会因为本线程被标记
为中断状态而抛出异常
回到正题
调用sleep函数就会抛出异常并且清除标记的状态,这样以来则会造成死循环了。所以要在catch中捕获到异常后再次中断下
*/
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
示例代码:最简单最常用的线程中断处理与线程优先级
package com.vince.thread;
public class ThreadDemo4 {
public static void main(String[] args) {
MyThread4 my=new MyThread4();
Thread t1=new Thread(my,"t1");
//设置线程优先级,并不是越高就100%能抢到cpu时间片,只是优先级越高,抢到几率更大一点。如果没有设置优先级则默认是5,10是最大优先级,1是最小优先级
t1.setPriority(Thread.MAX_PRIORITY);
t1.start();
MyThread5 my2=new MyThread5();
Thread t2=new Thread(my2,"t2");
t2.setPriority(Thread.MIN_PRIORITY);
t2.start();
for (int i = 0; i < 10; i++) {
System.out.println("main-"+i);
if(i==5){
//通过修改变量值来实现中断线程
my2.setFlag(false);
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//最常用的线程中断处理
class MyThread5 implements Runnable{
private boolean flag=true;
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
int i=0;
while(flag){
System.out.println(Thread.currentThread().getName()+"-"+i);
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread4 implements Runnable{
public void run(){
int i=0;
while (!Thread.interrupted()) {
System.out.println(Thread.currentThread().getName()+"-"+i);
i++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}
}
boolean isDaemon()
测试该线程是否为守护线程。
void setDaemon(boolean on)
将该线程标记为守护线程或用户线程。
static void yield()
暂停当前正在执行的线程对象,并执行其他线程。
当程序中没有用户线程时所有守护线程都会自动终止。守护线程守护的是用户线程。
虚拟机会启一个gc(垃圾回收)的线程,该线程就是守护线程,当程序结束了,gc也就自动终止了
示例代码:设置守护线程,守护线程与用户线程执行原理,判断是否为守护线程
package com.vince.thread;
public class ThreadDemo5 {
public static void main(String[] args) {
MyThread6 m6=new MyThread6();
Thread t1=new Thread(m6);
//设置t1为守护线程
t1.setDaemon(true);
//判断该线程是否为守护线程
System.out.println(t1.isDaemon());
t1.start();
//此处主线程的循环结束后就不会再继续循环t1线程的了,
//也就是说t1线程的程序不能执行完毕
//这是因为t1线程已经设置为守护线程,而主线程没有设置,没有设置的则为用户线程,而目前用户线程就只有这一个,而当用户线程任务完成后就会线程结束
//而当所有用户线程结束后守护线程也就会结束(无论该线程的程序是否执行完毕)
for (int i = 0; i < 10; i++) {
System.out.println("main-"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread6 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("MyThread6-"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
代码示例:线程让出自己的cpu时间片,又进入就绪状态,立即抢下次cpu时间片
package com.vince.thread;
public class ThreadDemo5 {
public static void main(String[] args) {
MyThread6 m6=new MyThread6();
Thread t1=new Thread(m6);
t1.start();
for (int i = 0; i < 10; i++) {
System.out.println("main-"+i);
if(i==5){
//让出当次cpu执行时间片,自己又进入就绪状态。然后又立即抢下一次的cpu执行时间片,程序执行的比较快,几乎和没有让出的情况差异不二,yield只让一次
Thread.yield();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MyThread6 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("MyThread6-"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
关键字词:javase,线程的操作方法