1. 程序、进程、线程的理解
程序(program):一段静态的代码,为完成特定任务、用某种语言编写的一组指令的集合。
进程(process):程序的一次执行过程,或是正在运行的一个程序。
线程(thread):进程可进一步细化为线程,是一个程序内部的一条执行路经。
2. 创建多线程的四种方式
方式一:继承Thread类的方式:
* 1.提供一个继承于Thread类的子类
* 2.重写Thread类的run():将创建的线程要执行的操作,声明在run()中。
* 3.实例化Thread子类
* 4.调用子类对象的start():①启动线程 ②调用当前线程的run()
说明两个问题:
1.能不能直接调用run(),去启动分线程?不能!
2.如何启动第二个分线程,必须重新创建一个Thread子类对象,不能使用原有的第一个Thread对象再次start()
方式二:实现Runnable接口的方式:
* 1.创建一个实现Runnable接口的类
* 2.实现Runnable中的run()
* 3.创建当前实现类的对象
* 4.将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象
* 5.通过Thread类的对象调用其start()
两种方式的对比:
* 1.联系:public class Thread implements Runnable
* 2.相同点:启动线程,使用的是同一个start()方法
*
* 3.对比:实现Runnable接口更好一些。
* 原因:1不影响类的继承。因为类是单继承的。
* 2 针对于共享数据的操作,更适合使用Runnable的方式。
*换句话说,实现Runnable接口的方式,实现了代码和数据的分离。
*************************
方式三:实现Callable接口 (jdk1.5以后)
class MyThread03 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("-----MyThread03");
return 200;
}
}
main(){
FutureTask futureTask = new FutureTask(new MyThread03());
new Thread(futureTask).start();
}
优点:①分线程执行的方法,可以有返回值 ②执行的方法可以抛出异常的。
方式四:使用线程池
//创建并使用多线程的第四种方法:使用线程池
class MyThread implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public class ThreadPool {
public static void main(String[] args) {
//1.调用Executors的newFixedThreadPool(),返回指定线程数量的ExecutorService
ExecutorService pool = Executors.newFixedThreadPool(10);
//2.将Runnable实现类的对象作为形参传递给ExecutorService的submit()方法中,开启线程
//并执行相关的run()
pool.submit(new MyThread());//线程.start()
pool.submit(new MyThread());
pool.submit(new MyThread());
//3.结束线程的使用
pool.shutdown();
}
}
3. Thread类中的常用方法
1.run():Thread的子类一定要重写的方法。将此分线程要执行的操作,声明在run()中
* 2.start():要想启动一个分线程,就需要调用start():①启动线程②调用线程的run()
* 3.currentThread():静态方法,获取当前的线程
* 4.getName():获取当前线程的名字
* 5.setName(String name):设置当前线程的名字
* 6.yield():当前线程调用此方法,释放CPU的执行权
* 7.join():在线程a中调用线程b的join()方法:只用当线程b执行结束以后,线程a结束阻塞状态,继续执行。
* 8.sleep(long millitimes):让当前的线程睡眠millitimes毫秒
* 9.isAlive():判断当前线程是否存活
* 10.线程的优先级:
* MAX_PRIORITY:10
* NORM_PRIORITY:5 ---默认优先级
* MIN_PRIORITY:1
*
* 设置优先级:setPriority(int priority);
* 获取优先级:getPriority();
*
* 设置优先级以后,对高优先级,使用优先调度的抢占式策略,抢占低优先级的执行。但是并不意味着高优先级的线程一定先于低优先级的线程执行,而是从概率上来讲,概率更大而已。
*************************************
* 线程通信:wait() / notify() / notifyAll() ---->java.lang.Object类中定义的方法
4. Thread的生命周期
5. 死锁问题
1).死锁的理解:
不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程的死锁
2).说明:死锁,是我们开发中需要规避的!
3).举例:
public class DeadLockTest {
public static void main(String[] args) {
StringBuffer s1 = new StringBuffer();
StringBuffer s2 = new StringBuffer();
new Thread(new Runnable() {
public void run() {
synchronized (s1) {
s1.append("a");// 类似s += "a"
s2.append("1");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s2) {
s1.append("b");
s2.append("2");
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
new Thread(new Runnable() {
public void run() {
synchronized (s2) {
s1.append("c");// 类似s += "a"
s2.append("3");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (s1) {
s1.append("d");
s2.append("4");
System.out.println(s1);
System.out.println(s2);
}
}
}
}).start();
}
}
7.sleep()与wait()的区别
* 1.方法声明在哪? Thread:sleep() Object:wait()
* 2.共同点:使得当前线程进入阻塞状态
* 3.使用的范围要求:sleep()使用没情境的要求;wait()必须使用在同步代码块或同步方法中
* 4.都使用在同步当中的话:wait()需要唤醒:notify()/notifyAll(); sleep():不会释放锁;wait()会释放锁
* 5.sleep是static方法,而wait是成员方法,