----------- android培训、java培训、java学习型技术博客、期待与您交流!------------
多线程
a.进程的概述和多进程的意义
进程: 就是正在执行的应用程序.
多进程的意义: 提高CPU的使用率.
如果一个计算机上同时启动了听音乐的进程和打游戏的进程,那么这两个进程是同时在执行吗?
不是,因为CPU在一个时间点上只能执行一个任务.而我们看到的像是在同时执行,那是因为CPU在这两个进程之间进行高效的切换.
b.线程的概述和多线程的意义:
线程: 一个应用程序可以有多个任务,而每一个任务可以看做成一个线程.如果一个应用程序只有一个任务,那么这个应用程序,就属于单线程应用程序.
如果一个应用程序存在朵儿任务,那么这个应用程序就属于多线程应用程序.
多线程的意义: 多线程的存在是提供了应用程序的使用率.
每一个应用程序在执行的时候都是在依赖于线程抢占CPU的时间片(执行权) , 如果有一个应用程序A只有一个线程,而另一个应用程序B
存在多个线程,那么那个应用程序抢占到CPU的执行权的概率大呢? 多个线程的应用程序B. 但是一定就是B应用程序抢占到CPU的执行权
吗? 不一定,所以我们多线程在执行的时候具有随机性.
c.JVM运行原理以及JVM启动的线程探讨
JVM的运行原理: 我们在使用java命令在运行一个程序的时候,其实是启动了JVM,而JVM的启动相当于一个进程.而同时这个进程会启动
一个线程,通过这个线程来调用main方法,而这个线程就是我们的主线程.
JVM的启动是多线程的吗?
是多线程的.因为JVM至少启动了两个线程,一个是主线程 , 一个是垃圾回收线程.
d: 实现多线程
两种方式:
第一种方式的步骤:
a: 创建一个类,然后让这个类去继承Thread类
b: 复写run方法(run方法中封装的都是要被线程执行的代码, run方法中代码的特点: 比较耗时的代码)
c: 创建a中定义的类的对象
d: 启动线程(启动线程使用的是start()方法)
public class MyThread extends Thread {
public void run() {
for(int x = 0 ; x < 100 ; x++){
System.out.println(x);
}
}
}
MyThread t1 = new MyThread() ;
MyThread t2 = new MyThread() ;
t1.start() ;
t2.start() ;
第二种方式的步骤:
a: 创建一个类,然后让这个类去实现Runnable接口
b: 复写run方法
c: 创建a中定义的类的对象
d: 创建Thread类的对象,然后把c中的对象作为参数传递
e: 启动线程
public class MyThread implements Runnable {
public void run() {
for(int x = 0 ; x < 100 ; x++){
System.out.println(x);
}
}
}
MyThread my = new MyThread() ;
Thread t1 = new Thread(my) ;
Thread t2 = new Thread(my) ;
t1.start() ;
t2.start() ;
线程调度:
调度模型:
a: 分时调度 就是给每一个线程分配指定的时间进行执行
b: 抢占式调度 优先的执行优先级高的线程,如果线程的优先级相同,那么就随机执行一个.每一个线程应该都存在一个默认的优先级.
而java语言采用的就是抢占式调度
如何获取线程的优先级?
public final int getPriority(): 获取线程的优先级(线程的默认优先级是: 5)
public final void setPriority(int newPriority): 给线程设置优先级(存在一个范围这个范围是1-10)
线程名称的问题:
如何获取线程的名称? public final String getName()
如何给线程设置名称? public final void setName(String name), 也可以通过构造方法进行设置
如何获取主线程的名称? 获取到当前正在执行的线程,然后在获取线程名称.如何获取到当前正在执行的线程.
在Thread类中存在一个静态的方法:
public static Thread currentThread():获取当前正在执行的线程.
线程控制:
线程休眠(掌握): public static void sleep(long time) ;
线程加入(了解): public final void join(); 等待该线程终止. 等待该线程执行完毕以后在执行其他的线程
线程礼让(了解): public static void yield(): 暂停当前正在执行的线程对象,并执行其他线程。
守护线程(了解): public final void setDaemon(boolean on):把指定的线程设置成一个守护线程.当执行的线程都是守护线程的时候,JVM停止运行
线程中断(掌握):
public final void stop(): 停止线程的运行
public void interrupt(): 打断阻塞状态. 继续执行下面的代码,但是该方法会抛出异常.
线程休眠案例:
/**
* 线程控制之线程休眠:
* public static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),
*/
public class ThreadDemo {
public static void main(String[] args) {
// 创建线程对象
MyThread t1 = new MyThread() ;
// 给线程设置名称
t1.setName("张三") ;
// 启动线程
t1.start() ;
}
}
public class MyThread extends Thread {
@Override
public void run() {
for(int x = 0 ; x < 100 ; x++) {
// 线程休眠
try {
Thread.sleep(2000) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + "----" + x);
}
}
}
线程中断案例:
public class Test1 {
/**
* 线程控制之线程中断: public final void stop(): 中断线程 public void interrupt(): 中断线程。
* 如果线程在调用 Object 类的 wait()、wait(long) 或 wait(long, int) 方法, 或者该类的
* join()、join(long)、join(long, int)、sleep(long) 或 sleep(long, int) 方法过程中受阻,
* 则其中断状态将被清除,它还将收到一个 InterruptedException。
*/
public static void main(String[] args) {
// 创建线程对象
MyThread t1 = new MyThread();
// 设置线程名称
t1.setName("宋承宪");
// 启动线程
t1.start();
try {
Thread.sleep(3000);
// 中断线程t1
t1.stop() ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程开始执行了.......");
try {
Thread.sleep(100000) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程任务结束了......");
}
}
数据安全的一个保证:
可以使用同步代码块:
格式:
synchronized(对象){
要被同步的代码 ;
}
同步代码块在保证数据的安全性主要依赖这个对象,要求使用的对象必须是同一个.这个对象可以看做成一把锁.
同步代码块的好处: 可以保证数据的安全性
同步代码块的弊端: 效率降低了
同步代码块以及同步方法和静态同步方法的锁对象的问题:
同步代码块的锁对象: 是任意的对象
同步方法的锁对象: 是this
静态同步方法的锁对象: 是该类对应的字节码文件对象.
案例:需求。有一百张电影票,三个窗口同时卖票。代码实现
public class SellTickets implements Runnable {
// 定义票的数量
private static int num = 100 ;
private static final Object obj = new Object() ;
private int n = 0 ;
@Override
public void run() {
while(true) {
if(n % 2 == 0){
synchronized(SellTickets.class) {
if(num > 0) {
try {
Thread.sleep(100) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + (num--) + "张票");
}
}
}else {
sellTickets() ;
}
n++ ;
}
}
// 静态同步方法
public static synchronized void sellTickets() {
if(num > 0) {
try {
Thread.sleep(100) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在出售第" + (num--) + "张票");
}
}
}
实现类
public class SellTicketsDemo {
public static void main(String[] args) {
// 创建SellTickets对象
SellTickets st = new SellTickets() ;
// 创建Thread对象
Thread t1 = new Thread(st , "窗口1") ;
Thread t2 = new Thread(st , "窗口2") ;
Thread t3 = new Thread(st , "窗口3") ;
// 启动线程
t1.start() ;
t2.start() ;
t3.start() ;
}
}
本文详细介绍了Java多线程的基本概念、JVM运行原理、实现方式、调度机制、线程控制等核心内容,包括进程与线程的区别、多线程的意义、JVM启动线程、线程调度模型、如何获取线程名称与优先级、线程控制方法如休眠、中断、礼让等,以及同步代码块和多线程数据安全的保证。

被折叠的 条评论
为什么被折叠?



