线程与进程:
进程是指一个内存中运行的应用程序,每个进程都有一个独立的内存空间,线程是进程中的一个执行路径,共享一个内存空间,线程之间可以自由切换,并发执行. 一个进程最少有一个线程;线程实际上是在进程基础之上的进一步划分,一个进程启动之后,里面的若干执行路径又可以划分成若干个线程。
继承Thread线程:
run()方法就是线程要执行的任务方法。
run()方法是新的执行路径,执行路径的出发方式,不是调用run()方法,而是通过Thread对象的start()方法来启动任务。
public class Demo{
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.start(); //通过start()启动线程
//java是抢占式调度
//主线程执行
for (int i=0;i<10;i++){
System.out.println("张三"+i);
}
}
}
//创建一个方法来继承Thread
class MyThread extends Thread{
//run()是用户线程要执行的任务方法
public void run(){
//这里的代码是新的执行路径
//这个执行路径的出发方式,不是调用run()方法,而是通过thread对象的start()方法来启动任务
for (int i=0;i<10;i++){
System.out.println("李四"+i);
}
}
}
实现Runnable
实现Runnable与继承Thread相比有如下优势
1、通过创建任务,然后给线程分配任务的方式实现多线程,更适合多个线程同时执行任务的情况 2、可以避免单继承所带来的局限性 3、任务与线程是分离的,提高了程序的健壮性 4、线程池技术,接受Runnable类型的任务,不接受Thread类型的线程
public class Demo1 {
public static void main(String[] args) {
//可以认为是创建一个任务对象
Runnable r = new MyRunnable();
//可以认是给线程r任务
Thread t = new Thread(r);
//启动线程
t.start();
//主线程
for (int i = 0; i < 10; i++) {
System.out.println("张三"+i);
}
}
}
//实现Runnable接口
class MyRunnable implements Runnable{
//重写run方法
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("李四"+i);
}
}
}
获取线程名称 Thread.currentThread().getName();
线程休眠 Thread.sleep(); 第一参数是毫秒,第二个参数是纳秒。
线程中断 使用中断标记t1.interrupt(),main线程结束,标记中断的被标记的线程进入catch块,
catch块中结束执行的任务就return,不return就不会中断。
线程分为守护线程和用户线程
用户线程:当一个进程不包含任何的存活的用户线程时,进行结束
守护线程:守护用户线程的,当最后一个用户线程结束时,所有守护线程自动死亡
设置守护线程 setDaemon(true); 括号里面有true是守护线程(不设置守护线程所有的线程默认为用户线程)
线程安全
1、同步代码块synchronized(锁对象){}
2、同步方法 synchronized修饰方法
3、显示锁 Lock 子类 ReentrantLock