最近跟着那个学习计划查漏 发现哪里都不懂
就一点一点补吧
比如多线程:
之前是仅仅知道怎么实现它 现在 好像还知道了一些其他的东西这篇博客大概涉及到
多线程概述
线程实现方案
线程调度和线程控制
线程生命周期
线程同步
首先 可能这篇博客话比较多 也会穿插自己写的例子帮助理解:
一 多线程概述
首先我们要知道线程是依赖进程存在的所以我们首先要知道什么是线程什么是进程
进程:
进程就是正在运行的程序 是系统进行资源分配和调用的独立单位
每一个进程都有自己的内存空间和系统资源
多进程的意义:
计算机可以做多件事情比如 一边玩游戏一边听音乐 提高cpu的使用率,但并不是同时进行因为cpu在某一个时间点上只能做一件事情 高效切换使我们感觉好像在同时进行
线程:
在一个进程内 可以执行多个任务 每一个任务我们可以看成一个线程
例如扫雷 有个计时器一直在跑 还可以点
还有迅雷下载
线程是程序的执行单元,执行路径。是使用cpu的基本单位
单线程:如果程序只有一条执行路径
多线程:多条执行路径
多线程的意义: 提高程序的使用率 程序的执行都是在抢夺cpu的资源
多个进程在抢这个资源 如果某一个进程的执行路径比较多 就有更大的几率抢到cpu的执行权
我们是不敢保证哪一个线程能够在哪一个时刻抢到所以线程的执行有随机性
还有并发和并行则两个概念
并行和并发:
并行:逻辑上同时发生 指的是在某一个时间段内同时运行多个程序
并发:物理上同时发生,指的是一个时间点同时运行多个程序
我们再来看一下java程序的运行原理
java程序的运行原理:
java命令会启动java虚拟机,启动jvm,等于启动了一个应用程序,也就是启动了一个进程 这个进程会自动启动一个主线程 然后这个主线程去调用某个类的main方法
所以main方法都是运行在主线程中的
jvm虚拟机的启动是多线程的 因为java有垃圾回收机制 垃圾回收线程也要先启动 属于多线程
二 实现多线程的方法
java提供了一个类叫Thread 我现在知道可以有二种方式实现多线程
1 继承Thread类
步骤:
A:自定义类MYThread类继承Thread类
B:MyThread类里面写run()
//run方法保证了这个线程肯定会执行的方法 因为类 里面的代码不一定全部被执行
C:创建对象
D:启动线程
举例:
public class MyThreadDemo {
public static void main(String args[] ){
MyThread myThread = new MyThread();
MyThread myThread1 = new MyThread();
myThread.start();
myThread1.start();
}
}
public class MyThread extends Thread{
public void run() {
// TODO Auto-generated method stub
//super.run();调用的父类没有意义
for(int i = 0;i<=10;i++){
System.out.println(i+" ");
}
}
}
2 :创建线程的另一种方法是声明实现Runnable接口的类 该类实现run方法 然后可以分配该类的实例 在创建Thread时作为一个参数来传递并启
步骤:
A:自定义类MyRunnable实现Runnable接口
B:重写run方法
C:创建MyRunnable类的对象
D:创建Thread类的对象 并把C步骤的对象作为构造参数传递
举例:
public class MyRunnable implements Runnable{
public void run() {
// TODO Auto-generated method stub
for (int x= 0;x<10;x++){
System.out.println(" "+x+Thread.currentThread().getName());
}
}
}
public class MyRunnableDemo {
public static void main(String [] args){
MyRunnable myRunnable = new MyRunnable();
Thread T1 = new Thread(myRunnable);
Thread T2 = new Thread(myRunnable);
T1.start();
T2.start();
}
}
那么 问题就来了 既然已经有方式一为什么还要有方式二呢?
哈哈哈 因为:因为java是单继承 实现接口的方式打破了单继承的局限性适合多个相同程序的代码去处理同一个资源的情况把线程同程序的代码数据有效分离 较好的体现了面向对象的设计思想
还有 启动线程的时候run()和start的区别()又是什么呢?
因为:一般来说 被线程执行的代码是比较耗时的
调用run方法是单线程的 run方法直接调用就等于普通方法调用
run是封装被线程执行的代码 直接调用是普通方法start 首先启动线程 然后由jvm去调用该线程的run方法注意会有可能被抛出非法的线程状态异常 同一个线程不能被调用两次
PS1:如何获取线程对象的名称:
getname();
PS2:如何设置线程对象的名称:
setname();
三 线程调度和线程控制
线程调度::
线程有两种调度模型:
分时调度 和抢占式调度模型 java使用的是抢占式的 取决于线程的优先级
线程默认的优先级是5 取值范围在1-10 线程优先级仅仅表示线程获取cpu时间片的几率高并不是一定先执行 因为具有随机性 只是优先级高而已
getPriority();可以得到当前的优先级
当然也就可以设置线程的优先级 setPriority();
线程控制之线程休眠:sleep();传入参数是毫秒值
线程加入:join()等待该线程终止
线程礼让:yield()暂停当前的线程先执行其他线程 线程礼让只能大程度的执行和谐一些、
线程中断:建议使用Interrupted()
这里我写了好多例子的 可是太多了 所以 大概就这些
啊啊啊啊觉得好棒!!
四 线程的生命周期
线程的生命周期:
新建:创建线程对象
就绪:有执行资格,没有执行权利
运行: 有执行资格有执行权
阻塞:由于一些操作使线程处于该状态没有执行资格也没有执行权 而另一些操作
可以激活 激活后处于就绪状态
死亡: 线程对象变成垃圾等待被回收
一张图来看一下啊:
五 线程安全的解决就是线程同步加锁
举例:某电影院目前正在电影 共有100张票 而它有3个售票窗口售票
然后就会出现线程安全问题
为什么会出现问题?
是否是多线程环境?
是否有共享数据
是否有多条语句操作共享数据
同步代码块的方式解决线程安全问题
前提:多线程 使用同一个锁
缺点:耗费资源 降低了程序的效率
使用:
**synchronized(对象);{
需要同步的代码;
}**
举个例子:
public class MyTicket implements Runnable {
private int tickets =100;
private Object obj = new Object();
//创建锁对象
public void run() {
// TODO Auto-generated method stub
while(true){
synchronized(obj ){
if(tickets>0){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets--+"张票");
}
}
}
}
}
这样就大概 就是我知道的多线程
今天一天都是多线程的人
over!