1.程序
程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一 段静态的代码。
2.进程
进程((process)正在内存中运行的应用程序,如运行中的QQ,运行中的音乐播 放器。进程是操作系统进行资源分配的最小单位。
3.线程
线程(thread)进程可进一步细化为线程,是一个进程内部的最小执行单元,是操 作系统进行任务调度的最小单元,隶属于进程。
注:
1.继承Thread类的方式
在Java中要实现线程,最简单的方式就是继承Thread类,并重写其中的run方法,方法原型如下:
①创建一个类继承Thread类
public class MyThread extends Thread{ }
②在该类中重写Thread类中的run方法
public class MyThread extends Thread{ // 重写run方法 @Override public void run() { for (int i = 0; i < 10000; i++) { System.out.println("MyThread:" + i); } } }
③在主线程中创建Thread对象,并调用start方法。
注意:启动线程是调用Thread中的start方法,不是调用run;调用run方法只是方法的调用,并不是启动线程。
public class Test { public static void main(String[] args) { // 创建线程对象 MyThread myThread = new MyThread(); // 启动线程要调用Thread中的start方法 myThread.start(); } }
2. 实现Runnable接口的方式
java.lang.Runnable接口中仅仅只有一个抽象方法,Runnable接口的存在主要是为了解决Java中不允许多重继承的问题。
public void run()
方法原型如下:
①创建一个类实现Runnable接口,并重写run方法
public class MyTask implements Runnable{ /* public abstract void run(); */ @Override public void run() { for (int i = 0; i < 10000; i++) { System.out.println("myTask:" + i); } } }
②在主线程中创建该类的对象
public class Test { /* 方法二: 实现Runnable接口,重写run方法 在主线程中创建继承类的对象, 再创建Thread对象中的构造方法,调用start方法 */ public static void main(String[] args) { // 创建类对象 MyTask myTask = new MyTask(); } } }
③再创建Thread对象中的构造方法,调用start方法
public class Test { public static void main(String[] args) { // 创建类对象 MyTask myTask = new MyTask(); // 创建线程对象,调用构造方法 Thread thread = new Thread(myTask); //多态 // 调用Thread中的start方法 thread.start(); //private native void start0();本地方法 } }
3.实现Runnable接口的好处
①避免了java中单继承的局限性
②多个线程可以共享同一个接口实现类的对象,非常适合多个相同线程来处理同一份资源。
方法原型 | 说明 |
---|---|
void start() | 启动线程 |
final String getName() | 返回线程的名称 |
final void setPriority(int newPriority) | 设置线程的优先级 |
final int getPriority() | 返回获取线程的优先级 |
final void join() | 等待线程终止 |
static Thread currentThread() | 返回对当前正在执行的线程对象的引用 |
static void sleep(long millis) | 让当前正在执行的线程休眠(暂停执行), 休眠时间由milli s(毫秒)指定 |
String getName() | 获取线程的名字 |
String setName() | 为线程设置名字 |
① MAX_PRIORITY:取值为10,表示最高优先级。
② MIN_PRIORITY:取值为1,表示最底优先级。
③ NORM_PRIORITY:取值为5,表示默认的优先级。
1.线程状态:
2.守护线程
方法 void setDamon(boolean on) 设置线程为守护线程(true)或用户线程(false)
必须在线程启动前设置
1.多线程的概念
多线程是指程序中包含多个执行单元,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。通俗来讲,就是在一个程序内部创建多个和线程执行任务。
2.什么时候使用多线程?
① 程序需要同时执行两个或多个任务。
② 程序需要实现一些需要等待的任务时,如用户输入、文件读写操作、 网络操作、搜索等。
3.多线程的优点
①同时执行多个任务,提高了代码的运行效率。
②多线程程序中,多个线程共享计算机的资源,提高了系统的资源利用率。
③多线程程序中,各个线程之间相互独立,易于维护和扩展。
④改善程序结构,将复杂任务分为多个线程,独立运行。
4.多线程的缺点
①线程也是程序,线程数过多,会影响程序的性能,消耗系统资源。
②多个线程同时访问共享资源,容易出现线程安全问题。
③多线程需要协调和管理,所以需要跟踪管理线程,使得cpu开销变大。
1.为什么采用线程同步
多个线程同时读写同一份共享资源时,可能会引起冲突。所以引入线同步机制, 即各线程间要有先来后到。
2.什么是同步
同步就是排队+锁:
几个线程之间要排队,一个个对共享资源进行操作,而不是同时进行操作;为了保证数据在方法中被访问时的正确性,在访问时加入锁机制。
3.解决方案
(1)使用synchronized关键字
synchronized关键字,修饰代码块和方法。
修饰代码块:synchronized(同步对象/同步锁){
// 多个线程对应的同步对象(同步锁)必须是同一个,用来记录有没有线程进入到同步代码块中。同步对象可以是 java中的任何类
}
修饰方法: synchronized修饰方法,同步对象会有默认的, 若修饰的方法是非静态方法,默认同步对象是this;若修饰的对象是静态方法,同步对象是当前类的class对象
package com.gty.thread.threadDemo5;
public class PrintNumTask extends Thread {
static int num = 1;
static Object object = new Object();
@Override
public void run() {
while (true) {
synchronized (object) {
// 唤醒
object.notify();
if (num <= 100) {
System.out.println(Thread.currentThread().getName() + ":" + num);
num++;
} else {
break;
}
try {
// 等待
object.wait();
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
package com.gty.thread.threadDemo5;
public class Test {
public static void main(String[] args) {
PrintNumTask printNumTask1 = new PrintNumTask();
PrintNumTask printNumTask2 = new PrintNumTask();
printNumTask1.setName("线程1");
printNumTask2.setName("线程2");
printNumTask1.start();
printNumTask2.start();
}
}
(2)Lock(锁),ReentratLock
Lock lock = new ReentratLock;
ReentratLock实现了Lock接口,所以可以称为Lock锁。
与synchronized相比:
①ReentratLock是一种java代码层的控制实况
②而ynchronized是关键字,依靠底层编译后的指令实现;而ReentrantLock是一个类。
③synchronized用于修饰代码块和方法,ReentrantLock只能修饰代码块。
④synchronized属于隐式的加锁和释放锁,而ReentrantLock要通过手动加锁和释放锁,释放锁最好在 finally代码块中运行。
1.概念
线程通讯指的是多个线程通过相互牵制,相互调度,即线程间的相互作用。
2.三个方法
注意:wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。
3.wait()和sleep()区别
wait():
①线程等待,需要被唤醒;
②会释放锁;
③只能在同步代码块中使用。
sleep():
①线程睡眠,不需要被唤醒,睡眠时间结束会自动启动;
②不会释放锁;
③可以在任何地方使用。