1、实现多线程编程的两种方式;
(1)继承Thread类
public class TestThread extends Thread{
@Override
public void run() {
/*do something*/
}
public static void main(String[] args) {
TestThread t1=new TestThread();
t1.start();
}
}
(2)实现Runnable接口
public class MyThreadRunnable implements Runnable{
@Override
public void run() {
/*do something*/
}
public static void main(String[] args) {
MyThreadRunnable t1=new MyThreadRunnable();
Thread thread=new Thread(t1);
thread.start();
}
}
Thread类也实现了Runnable接口:
class Thread implements Runnable{
private static native void registerNatives();
static {
registerNatives();
}
}
Thread类的构造函数:
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
//设置用户组,传入线程名,实现Runnable接口的对象,设置当前线程栈大小
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
2、Thread类常用方法
(1)Thread.currentThread()返回一个线程,该线程为正在执行当前代码段的线程。
在start()方法调用前 TestThread类对象仅当做一个普通的对象来看待。
public class TestThread extends Thread{
public TestThread() {
System.out.println("构造方法打印:"+Thread.currentThread().getName());
}
@Override
public void run() {
/*do something*/
System.out.println("run方法打印:"+Thread.currentThread().getName());
}
public static void main(String[] args) {
TestThread t1=new TestThread(); //输出:构造方法打印:main
t1.start();//输出:run方法打印:Thread-0
t1.run();//输出:run方法打印:main
}
}
(2)Thread.isAlive()判断当前线程是否处于活动状态。
public class TestThread extends Thread{
@Override
public void run() {
/*do something*/
System.out.println("run="+this.isAlive());
}
public static void main(String[] args) {
TestThread t1=new TestThread();
System.out.println("begin="+t1.isAlive());//输出begin=false
t1.start();//输出:run=true
System.out.println("end="+t1.isAlive());//输出end=?(不确定)
}
}
note:this和Thread.currentThread是不一样的!!!!
(3)Thread.sleep()让当前正在执行的线程休眠
(4)Thread.getId()取得线程的唯一标识
(5)线程停止:interrupt()方法+抛异常
相关函数:
Thread.interrupt()将一个线程标记为中断(但实际仍然会继续执行);
t.interrupted()测试当前线程(执行this.interrupted()的线程,和线程 t 无关)是否已经中断,类型为:public static boolean
interrupted()函数具有清除状态的功能。如果连续两次调用该函数,返回值会不一样!!!
t.isInterrupted()测试线程 t 是否已经中断,类型为:public boolean
public class TestThread extends Thread{
@Override
public void run() {
/*do something*/
super.run();
try {
for(int i=0;i<500000;i++) {
if(TestThread.interrupted()) {
throw new InterruptedException();
}
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
try {
TestThread t1=new TestThread();
t1.start();
Thread.sleep(2000);
t1.interrupt();
}catch(InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
}
note:
interrupt()方法和return结合也能达到停止线程的目的,不过建议使用抛异常的方法,因为catch块还可以将异常向上抛,达到异常传播的目的。
不推荐使用stop()暴力终止异常,会立即终止,可能造成数据不一致的现象。
(6)线程暂停:
t.suspend()暂停线程 t
t.resume()恢复运行线程 t
缺点:1、独占某个公共的同步对象,使得其他线程无法访问公共同步对象。一旦a线程suspend了,其他线程将永远无法执行printString函数。
public class SynchronizedObject{
synchronized public void printString() {
System.out.println("begin");
if("a".equals(Thread.currentThread().getName())) {
System.out.println("a线程永远suspend了");
Thread.currentThread().suspend();
}
System.out.println("end");
}
}
2、数据不同步现象
线程t1执行setValue,而线程t2执行printUsernamePassword会输出:
停止a线程
a 11
public class Myobject{
private String username="1";
private String password="11";
public void setValue(String u,Sring p) {
this.username=u;
if(Thread.currentThread().getName().equals("a")) {
System.out.println("停止a线程");
Thread.currentThread().suspend();
}
this.password=p;
}
public void printUsernamePassword() {
System.out.println(username+" "+password);
}
}
(7)Thread.yield()放弃当前的CPU资源,让给其他的任务去抢占,可能刚刚放弃,马上又获得CPU时间片
(8)t.setPriority(int priority)设置线程的优先级,优先级具有继承性:A线程启动B线程,则A和B的优先级相同。
(9)t.setDaemon(true)将线程t设置为守护线程:
守护线程是为其他线程的运行提供服务,只要当前jvm中存在任何一个非守护线程,Daemon就在工作,守护线程最典型的应用是GC(即垃圾收集器)
public class MyThread extends Thread{
private int i=0;
@Override
public void run() {
try {
while(true) {
i++;
System.out.println("i="+i);
Thread.sleep(1000);
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
public class Run{
public static void main(String[] args) {
try {
MyThread thread=new MyThread();
thread.setDaemon(true);
thread.start();
Thread.sleep(5000);
System.out.println("main线程终止了,damon线程也随之终止,不在打印");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
输出结果为:
i=1
i=2
i=3
i=4
i=5
main线程终止了,damon线程也随之终止,不在打印