我的java日记(多线程)
来源:互联网 发布:java逆序输出数组 编辑:程序博客网 时间:2024/05/16 10:39
经验是积累出来的,只有每天不断的进步,才能超越,只有每天不断的学习才能进步.通过这些天看毕向东老师的视频,让我学到了很多的东西,以前不懂的现在也逐渐的明了了.
下面是我这两天学习多线程总结的知识点.:
多线程:
1:进程:当前正在进行的程序,代表的是应用程序在内存中的执行区域.
线程:是进程中的一个执行单元,执行路径,负责的是程序的执行.一个进程中至少有一个线程在负责程序的执行.
单线程程序:一个正在运行的程序只有一条执行路径(单元),那么,这个程序就称为单线程程序.
多线程程序:一个正在运行的程序有多条执行路径(单元),这个程序就称为多线程程序.
例:360图形管理界面可以同时运行电脑体检和木马查杀等,这就相当于在360中有多天执行路径;
迅雷下载工具可以同时下载多个.
2:jvm启动至少启动两个线程:主方法和垃圾回收.
假如:jvm的启动时单线程的,那么,程序在执行过程中就会有内存溢出这样的隐患,而我们使用java程序时,
没有这个问题.说明垃圾回收机制是早就启动了.
jvm启动有两条执行程序,一条用于执行程序,一条用于执行垃圾回收.所以jvm的启动是多线程的.
3:线程是进程的执行路径,而进程是由windows创建的,java语言不能直接操作系统底层.
4:
(1)创建线程的第一种方式:
A:继承Thread类
B:覆写Thread类中的run方法;
C:创建自定义类的对象.
D:调用start()方法,开启线程
(2)创建线程的第二种方式:Runnable
A:自定义类实现Runnable接口.
B:实现该接口中的run方法
C:创建Thread类的对象,把自定义的对象传递给Thread类的构造方法中.
D:调用Thread类中的start方法.
例:public class RunnableDemo implements Runnable{
public void run(){
//code
}
}
public class RunnableDemoTest{
public static void main(String[] args){
Runnable r=new Runnable();
Thread t1=new Thread(r);
Thread t2=new Thread(r)
t1.start();
t2.start();
}
}
在Runnable中使用Thread.currentThread().getName();取得线程名称.
5:为什么要继承Thread类,并重写run方法呢?
因为:我们没有办法直接创建线程类,必须通过API提供的Thread类来做.
线程执行的代码都是放在run方法中,如果我们不重写run,那么将调用的是Thread类的默认处理方式.
6:Thread类中的常用方法:
start():开启线程,Java虚拟机默认调用该线程的run方法.
String getName():返回当前线程的名称.如果没有指定线程名称,默认会给出名字:Thread-x(0,1...);主线程的名字是main
static Thread currentThread():返回当前正在执行的线程对象的引用,
用于不是Thread类子类的类获取线程名称:Thread.currentThread().getName();
void setName("线程名字");为线程定义名字.
Thread(String name):通过构造方法给线程设置名称.
7:线程的随机性原理:
CPU的特点:在任一时刻(点),只能有一个线程在执行.windows中的任务同时执行,其实就是多个应用程序同时在执行,
而每一个应用程序的执行是由线程控制的.
windows系统是多线程的操作系统.
由于我们所说的同时执行,其实是多个应用程序不断的争抢CPU的资源.谁抢到,就具有执行权,那么,这个应用程序就会执行.
因为CPU的切换速度是xx分之一毫秒.
8:线程的运行状态:
线程的声明周期中每个状态的特点:
新建:通过继承Thread类,并在测试类中创建了对象.
就绪:通过start()方法,具有了执行资格,没有执行权.
运行:具有执行资格,具有执行权.
(阻塞):运行过程中由于某些原因(wait,sleep),释放了执行权和执行资格.
当然,他们可以回到运行状态,只不过,不是直接回到.
死亡:对象在内存中变成垃圾,(1)run方法执行完毕.(2)stop()
notify()唤醒
sleep()睡眠
9:(1)产生线程安全的原因
A:多个线程访问出现延迟。
B:线程访问的随机性
注:线程安全问题在理想状态下,不容易出现,但一旦出现对软件的影响是非常大的。
(2)如果判断一个线程程序有没有安全问题呢?
A:多个线程操作共享数据
B:这个操作是分多条语句执行的。
(3)解决线程安全问题的方式
A:同步代码块
B:格式:
synchronized(对象)
{
//需要被同步的代码
}
10:线程同步:为了解决安全问题.
格式: synchronized(对象){需要被同步的代码;}例:火车上上厕所.
(1)同步代码块的锁是任意同一对象都可以的.
(2)当你发现你使用了同步后,任然没有解决线程安全问题,这个时候,就需要考虑使用的是否是同一把锁.
同步的前提:
同步需要两个或者两个以上的线程.
多个线程使用的是同一个锁.
未满足这两个条件,不能称其为同步.
同步的弊端:
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗资源的,无形中会降低程序的运行效率.
一:同步函数:解决线程安全问题的第二种方法:
格式:就在方法上加synchronized关键字.
同步方法的锁到底是哪个对象呢?
通过同步测试,发现,同步方法锁对象是this.
即:synchronized(this){ }
静态方法的锁是:当前类的class文件的类对象.
A:当一个方法的方法体都被同步代码块包围起来了.我们就可以使用另外一种方式来表示.就死同步方法
B:同步方法的使用格式非常简单,就是在方法声明上加同步关键字.
C:同步方法的锁是什么呢?如何测试呢?
同步方法的锁是this对象.
通过在run里面同步使用同步方法和同步代码块来测试的.
D:静态方法的锁是什么呢?
静态方法的锁是当前类class文件描述类对象.
当局部有可能出现问题时用同步代码块.
11:死锁:
产生原因:有两个锁,在A锁中使用B锁,在B锁中使用A锁.就会造成死锁问题.
解决方案:不写出死锁的代码.
例:
public class DieLock implements Runnable{
private boolean flag;
public DieLock(){}
public DieLock(boolean flag){
this.flag = flag;
}
@Override
public void run() {
if(flag){
synchronized (MyLock.myLocka) {
System.out.println(Thread.currentThread().getName()+"if mylocka");
synchronized (MyLock.myLockb) {
System.out.println(Thread.currentThread().getName()+"if mylockb");
}
}
}
else
{
synchronized (MyLock.myLockb) {
System.out.println(Thread.currentThread().getName()+"else mylockb");
synchronized (MyLock.myLocka) {
System.out.println(Thread.currentThread().getName()+"else mylocka");
}
}
}
}
}
public class DieLockTest {
public static void main(String[] args) {
DieLock d1 = new DieLock(false);
DieLock d2 = new DieLock(true);
Thread t1 = new Thread(d1);
Thread t2 = new Thread(d2);
t1.start();
t2.start();
}
}
12:线程间的交互(通信):
多个线程加锁的时候要注意:
A:对多个线程都要加锁.
B:这多个线程必须使用同一把锁
void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
释放执行权,并释放锁.被唤醒的线程会继续往下执行.
例:
public class Student {
private Student(){}
private static Student s=new Student ();
public static Student getSingle() {
return s;
}
String name;
int age;
boolean flag = false;
}
public class InputStudent implements Runnable {
Student s=Student.getSingle();
public InputStudent() {}
public InputStudent(Student s) {
this.s = s;
}
public void run() {
int x = 0;
while (true) {
synchronized (s) {
//如果我们有值,我们就等待。
if(s.flag){
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (x % 2 == 0) {
s.name = "林青霞";
s.age = 20;
} else {
s.name = "刘德华";
s.age = 40;
}
//唤醒打印线程
s.flag = true;
s.notify();
}
x++;
}
}
}
public class OutputStudent implements Runnable {
Student s=Student.getSingle();
public OutputStudent() {
}
public OutputStudent(Student s) {
this.s = s;
}
@Override
public void run() {
while (true) {
synchronized (s) {
if(!s.flag){
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(s.name + "***" + s.age);
s.flag = false;
s.notify();
}
}
}
}
public class ResourceTest {
public static void main(String[] args) {
Student s = Student.getSingle();
InputStudent is = new InputStudent(s);
OutputStudent os = new OutputStudent(s);
Thread t1 = new Thread(is);
Thread t2 = new Thread(os);
t1.start();
t2.start();
}
}
13:wait和sleep的区别:
A:对于时间的指定:
sleep()必须要指定时间
wait()方法有重载的形式,可以指定时间,也可以不指定时间.
B:执行权和锁的释放:
sleep()释放执行权,不释放锁.
wait()释放执行权,释放锁.
14:停止线程:
A:run方法自动结束
B:使用interrupt()方法
C:可以通过控制循环条件结束.
15:常用方法:
(1) interrupt():用于中断一个线程,抛出一个InterruptedException异常.
例:
public class InterruptDemo {
public static void main(String[] args) {
StopThread st = new StopThread();
Thread t1 = new Thread(st, "刘恺威");
Thread t2 = new Thread(st, "杨幂");
t1.start();
t2.start();
// 让主线程也参与
int count = 0;
while (true) {
if (count++ == 50) {
t1.interrupt();
t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName() + "***" + count);
}
}
}
(2) setDaemon(boolean b):将该线程标记为守护或用户线程.也称为后台线程.当主线程结束后,后台自动结束.
例:
public class SetDaemonDemo {
public static void main(String[] args) {
StopThread st = new StopThread();
Thread t1 = new Thread(st, "刘恺威");
Thread t2 = new Thread(st, "杨幂");
//设置守护线程
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
// 让主线程也参与
int count = 0;
while (true) {
if (count++ == 50) {
break;
}
System.out.println(Thread.currentThread().getName() + "***" + count);
}
}
}
(3) join():加入线程,让其他的所有线程都给加入线程让路(即先执行加入线程).
加入线程执行完毕后,其他线程继续抢夺资源执行.
例:
public class JoinDemo {
public static void main(String[] args) {
Demo d = new Demo();
Thread t1 = new Thread(d,"宋江");
Thread t2 = new Thread(d,"方腊");
t1.start();
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
for (int x = 0; x < 100; x++) {
System.out.println(Thread.currentThread().getName() + "***" + x);
}
}
}
(4) setPriority(int newPriority):更改线程的优先级
getPriority():得到线程的优先级.
线程优先级1-10;线程的默认优先级是5.
static int MAX_PRIORITY 线程可以具有的最高优先级。10
static int MIN_PRIORITY 线程可以具有的最低优先级。5
static int NORM_PRIORITY 分配给线程的默认优先级。 1
例:
public class PriorityDemo {
public static void main(String[] args) {
Demo d = new Demo();
Thread t1 = new Thread(d, "关羽");
Thread t2 = new Thread(d, "赵云");
Thread t3 = new Thread(d, "张飞");
// System.out.println(t1.getPriority());
// System.out.println(t2.getPriority());
// System.out.println(t3.getPriority());
t3.setPriority(10);
t1.setPriority(1);
t1.start();
t2.start();
t3.start();
// System.out.println(t1);
// System.out.println(t2);
// System.out.println(t3);
}
}
(5) toString():返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
(6) yield():暂停当前正在执行的线程对象,并执行其他线程,让线程的执行趋近于平衡(礼让)。Thread.yield();
- 我的java日记(多线程)
- 我的Java日记
- 我的java培训日记
- 我的java日记(基础上)
- 我的Java日记--Char
- 我的JAVA日记 一
- 我的JAVA日记 二
- 我的JAVA日记 三
- 我的Java学习日记
- 【学习日记】java多线程的知识点总结
- 我的java培训日记-2
- 我的java培训日记-3
- 我的java培训日记-4
- 我的java培训日记-1
- 我的java培训日记-1
- 我的java培训日记-1
- 我的java培训日记-2
- 我的java培训日记-3
- adb操作命令
- 深入浅出FPGA-11-梦回大唐
- watir文件路径相关
- 为什么要有环回路由(zz)
- 【hdu 1728】 逃离迷宫 广搜(最少拐弯次数)
- 我的java日记(多线程)
- 笔记二
- oracle中SQL语句增、删、改、查
- Android下ListView上下滑动背景变黑
- 垃圾回收的算法与方式
- 行列式_part1
- 数据库总结过程
- Checkbox的checked属性问题
- oracle中查询:子查询,连接查询