线程,进程相关概念
进程
进程:正在运行的应用程序,一个电脑可以有多个进程,但在某一时刻/时间点(单核)CPU只能执行一个进程;CPU可以在多个进程间进行高速转换;
线程
- 线程:依赖于进程,进程开启后,会执行很多的任务,而将每个任务,称之为线程
- 线程具有随机性,会去抢占CPU的执行权,谁获得CPU的执行权,谁执行;但每一时刻只能执行一个线程
- 进程是拥有资源,且CPU执行的是线程
- 进程是拥有资源的基本单位,线程是CPU调度的基本单位。
单线程、多线程还境浅层概述
- 单线程环境:只有一条执行路径
- 多线程环境:具有多条执行路径
多线程意义
- 提高应用程序的使用率,提高CPU利用率。
多线程并发与并行
- 多线程并发:指在某一时刻同时运行多个程序;
- 多线程并行:指在某一时间段内同时运行多个程序;
Java中如何开启一个线程
方法一:
- 继承Thread类;
- 重写Thread类中run()方法;
- 调用start()方法,开启线程;
继承Thread类:
public class myThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(i);
}
}
}
开启线程:
public class test {
public static void main(String[] args) {
myThread myThread = new myThread();
myThread.start();
}
}
方法二:
- 实现Runnable接口;
- 重写接口中的run()方法;
- 建立Runnable接口子对象,将其作为参数传进Thread的构造方法中,建立Thread类对象;
- 调用start()方法,开启线程;
实现接口:
public class myThread1 implements Runnable {
@Override
public void run() {
System.out.println("我进来了!");
}
}
开启线程:
public class test1 {
public static void main(String[] args) {
myThread1 myThread1 = new myThread1();
Thread thread = new Thread(myThread1);
thread.start();
}
}
方法三:
- 实现Callable接口;
- 重写接口中的call()方法(注此方法具有返回值,有需求可以使用方法三);
- 建立Callable接口子对象,将其作为参数传进FutureTask的构造方法中,建立FutureTask子对象,将其作为参数传进Thread的构造方法中,建立Thread类对象;
- 调用start()方法,开启线程;
实现接口:
public class myThread2 implements Callable {
@Override
public Object call() throws Exception {
System.out.println("我又进来了");
return null;
}
}
开启线程:
public class test2 {
public static void main(String[] args) {
myThread2 myThread2 = new myThread2();
FutureTask<Object> task = new FutureTask<Object>(myThread2);
Thread thread = new Thread(task);
thread.start();
}
}
线程的相关方法
- getName() // 获取线程名
- setName(String name) //重置新的线程名
- currentThread()//获取当前执行的线程
- currentThread().getName() //获取当前执行的线程名
- getPriority() //获取线程的优先级
- setPriority(int newPriority)//设置线程的优先级(参数范围1-10)
注:建立线程的优先级的大小仅仅表示这个线程被CPU执行的概率增大了.但是多线程具有随机性,所以效果不是很明显,且线程的默认优先级是5 - sleep(long millis) // 线程休眠(也就是暂停millis毫秒后,在执行后面代码,调用方式为Thread.sleep(1000) )
- join() // 使线程串行运行,即一个运行完后,其他在运行
注: 在线程启动之后,在调用方法 - yield(): // 暂停当前正在执行的线程对象,并执行其他线程;调用格式为:Thread.yield()(理想化状态)
- setDaemon(boolean on) //将该线程标记为守护线程或用户线程。
注:当主线程运行完后,守护线程随之停止,该方法必须在启动线程前调用。
守护线程代码演示:
myThread myThread = new myThread();
myThread.setDaemon(true);
myThread.start();
System.out.println("我真的疯了");
System.out.println("我真的疯了");
System.out.println("我真的疯了");
System.out.println("我真的疯了");
System.out.println("我真的疯了");
- stop(): // 停止线程的运行
- interrupt(): // 中断线程的阻塞状态
线程的安全性问题、解决方法
- 形成安全问题,需满足条件
1. 多线程
2. 多线程存在并发操作共享数据
3. 多条语句操作共享数据
- 解决方法
方法一: 使用同步代码块
格式:
synchronized(锁){
有可能出错的代码;
}
注:此时的锁,是任意类型的对象
代码演示
synchronized (Bianliang.obja) {
System.out.println("true"+Bianliang.obja+"进来了");
}
方法二: Lock锁
ReentrantLock类中的 lock() //加锁 ,unlock() //去掉锁
格式:
ReentrantLock lock = new ReentrantLock();
lock.lock();
有可能出错的代码;
lock.unlock();
注:此方法最好放在try,catch,finally中,确保锁的释放
同步代码块、同步方法、同步静态方法锁对象的类型
- 同步代码块:任意对象
- 同步方法:this
- 静态同步方法:就是当前类对应的字节码文件对象(如:Thread.class)
死锁概述、实现
概述:是指两个或者两个以上的线程在执行的过程中,因争夺资源产生的一种互相等待现象(如果出现了同步嵌套,就容易产生死锁问题)
### 同步嵌套实现
public class myThread extends Thread {
boolean flag;
public myThread(boolean s) {
this.flag=s ;
}
@Override
public void run() {
/* ReentrantLock lock = new ReentrantLock();
lock.lock();
lock.unlock();*/
if(flag){
synchronized (Bianliang.obja){
System.out.println("true"+Bianliang.obja+"进来了");
synchronized (Bianliang.objb){
System.out.println("true"+Bianliang.objb+"进来了");
}
}
}else{
synchronized (Bianliang.objb){
System.out.println("false"+Bianliang.objb+"进来了");
synchronized (Bianliang.obja){
System.out.println("false"+Bianliang.obja+"进来了");
}
}
}
}
}
### 线程开启
public class test {
public static void main(String[] args) {
myThread thread1 = new myThread(true);
myThread thread2 = new myThread(false);
thread1.start();
thread2.start();
}
}
### 相关变量声明
public class Bianliang {
static Object obja =new Object();
static Object objb =new Object();
}
案例实现(多线程实现多窗口卖票)
### 继承Thread类,重写run方法
public class myThread extends Thread {
static int i=1000; //票数
Object obj = new Object (); //同步代码块中的锁
public myThread(String s) {
super (s);
}
@Override
public void run() {
while (true){
synchronized (obj){
if(i>=1){
System.out.println(this.getName()+"正在出售第"+(i--)+"张票");
}else{
break;
}
}
}
}
}
### 线程开启
public class test {
public static void main(String[] args) {
myThread thread1 = new myThread("窗口一");
myThread thread2 = new myThread("窗口二");
myThread thread3 = new myThread("窗口三");
thread1.start();
thread2.start();
thread3.start();
}
}