1、多线程是什么
多线程改变了代码的执行方式,从原有的所有代码
都串行操作改变为多个代码片段之间并行操作。
因此多线程允许多个代码片段"同时运行"。
2、创建线程的方式
创建线程的方式主要有两种。
- 在类中继承线程,并且重写类的方法run方法,在run方法中定义线程的任务
启动线程是调用线程的start方法而不是
直接调用run方法。
当线程的start方法调用后,线程纳入到
线程调度中,当其第一次分配到时间片开
始运行时,它的run方法会自动被执行。
class MyThread1 extends Thread{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("你愁啥?");
}
}
}
class MyThread2 extends Thread{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("瞅你咋地!");
}
}
}
public class ThreadDemo1 {
public static void main(String[] args) {
Thread t1 = new MyThread1();
Thread t2 = new MyThread2();
t1.start();
t2.start();
}
}
我们看到上面的代码,可以得知
这种创建线程的方式优点是创建简单方便
但是缺点也比较明显:
1:由于java是单继承的,这导致继承了线程就
无法再继承其他的类,这会导致无法重用其他
超类的方法而产生继承冲突问题。
2:定义线程的同时重写run方法,这就等于规定了
线程要执行的具体任务,导致线程与其执行的
任务产生必然的耦合关系,不利于线程的重用
3、创建线程的方式(二):
public class ThreadDemo2 {
public static void main(String[] args) {
//单独实例化任务
Runnable r1 = new MyRunnable1();
Runnable r2 = new MyRunnable2();
//创建线程
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
}
}
class MyRunnable1 implements Runnable{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("你愁啥?");
}
}
}
class MyRunnable2 implements Runnable{
public void run() {
for(int i=0;i<1000;i++) {
System.out.println("瞅你咋地!");
}
}
}
我们可以看出我们使用的是implements关键字,不影响我们的此类去继承父类
4、线程优先级
线程的优先级
线程启动后就纳入到了线程调度中统一管理,
什么时候获取CPU时间片完全取决于线程调度,
线程是不能主动索取的,通过调整线程的优先级
可以最大程度的干涉分配CPU时间片的几率。
理论上线程优先级越高的线程获取CPU时间片的
几率越高。
线程的优先级有10个等级,用整数1-10表示,
1是最小,5是默认,10是最高
下面来获取线程的信息和优先级
public class ThreadInfoDemo {
public static void main(String[] args) {
//获取主线程
Thread main = Thread.currentThread();
//获取线程的名字
String name = main.getName();
System.out.println("name:"+name);
//获取唯一标识
long id = main.getId();
System.out.println("id:"+id);
//获取线程的优先级
int priority = main.getPriority();
System.out.println("优先级:"+priority);
boolean isAlive = main.isAlive();
boolean isDaemon = main.isDaemon();
boolean inInterrupted = main.isInterrupted();
System.out.println("isAlive:"+isAlive);
System.out.println("isDaemon:"+isDaemon);
System.out.println("inInterrupted:"+inInterrupted);
}
}
5、线程Sleep方法 static void sleep(long ms)
该方法可以让运行这歌方法的线程处于阻塞状态,指定的毫秒,超过后线程会自动回到RUNNBALE状态在此并发运行
public class SleepDemo {
public static void main(String[] args) {
System.out.println("程序开始了");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程序结束了");
}
}
6、守护线程
守护线程
守护线程也称为后台线程,创建和使用上与前台
线程一样,但是有一点不同:
当进程结束时,所有正在运行的守护线程都会被
强制停止。
进程的结束:当所有普通线程都结束时,进程结束
public class DaemonThreadDemo {
public static void main(String[] args) {
Thread rose = new Thread() {
public void run() {
for(int i=0;i<5;i++) {
System.out.println("rose:let me go!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
System.out.println("rose:啊啊啊啊啊啊AAAAAAaaaaa....");
System.out.println("噗通!");
}
};
Thread jack = new Thread() {
public void run() {
while(true) {
System.out.println("jack:you jump!i jump!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
};
rose.start();
/*
* 设置为守护线程要在线程启动前进行
*/
jack.setDaemon(true);
jack.start();
}
}