知识点一:进程,线程与多线程
Windows系统号称多任务(可以同时运行多个应用程序)。
宏观上看: windows确实是允许了多个程序。
微观上看:cpu快速切换执行任务,由于速度特别快,我们人感觉不到这个切换的过程。
1.进程:就是正在运行的程序,分配内存让应用程序能够运行。
2.线程:线程在一个进程中负责代码的执行, 就是一个进程中的执行路径。
3.思考
A.没有学习线程,为什么代码可以执行?
java程序在运行的时候,jvm会帮我们创建一个主线程来执行代码。主线程主要负责main方法中的代码执行。
B.一个java程序中至少有2个线程
一个是主线程只要负责main方法中的代码执行,一个垃圾回收器线程,负责垃圾回收。
4.多线程 :在一个进程中多个线程同时执行不同的任务。
"同时":单核CPU快速切换多个线程执行任务,速度特别快,我们人感觉不到切换。
4.1多线程的好处:
a.解决一个进程中同时执行多个任务的问题。
b.提高资源的利用率。
4.2多线程的弊端:
a.增加CPU的负担。不线程越多越好。
b.降低了一个进程中线程的执行概率。
c.容易引发线程安全问题。
d.出现死锁现象。
知识点二:创建线程的两种方式
方式一:Thread (线程类)
1.需要定义一个类来继承Thread类
2.重写thread类中run方法,把自定义线程的任务代码写在run方法中。每一个线程都有自己的任务代码 ,jvm创建的主线程的任务代码就是main方法,自定义的线程的任务代码就写下run方法中,自定义的线程就需要来执行run方法中的代码
3.创建Thread的子类,并且调用start方法开启线程
注意点:
一旦线程开启了,会默认执行线程对象中的run方法, 但是千万不要自己直接调用run方法,如果直接调用了run方法就和普通方法没有区别
class MyThread extends Thread {
@Override
public void run() { //多线程执行任务的地方
//自定义线程的任务代码
for(int i = 0;i<100;i++){
System.out.println("多线程:"+i);
}
}
}
public class Demo1 {
public static void main(String[] args) { //从上到下依次执行。
// TODO Auto-generated method stub
//创建一个自定义线程对象
MyThread t = new MyThread();
//开启线程来执行任务
t.start();
//main方法中的代码是在主线程中执行的
for(int i = 0;i<100;i++){
System.out.println("主线程:"+i);
}
}
}
线程中常用的方法:
Thread(String name)初始化线程的名字
getName()返回线程的名字
setName(String name)设置线程对象名
sleep()线程睡眠指定的毫秒数。
getPriority()返回当前线程对象的优先级 默认线程的优先级是5
setPriority(int newPriority)设置线程的优先级 虽然设置了线程的优先级,但是具体的实现取决于底层的操作系统的实现 (最大的优先级是10,最小的1, 默认是5)。
currentThread()返回CPU正在执行的线程的对象
public class Demo3 extends Thread{
//定义一个构造方法来调用父类的构造方法。
public Demo3 (String name){
super(name);
}
//重写run方法
@Override
public void run() {
// TODO Auto-generated method stub
for(int i = 0;i<50;i++){
//设置线程睡眠0.5秒 单位是毫秒
//异常只能处理 :thread父类中run方法没有抛出异常,所以子类也不允许抛出异常。
/*try {
//Thread.sleep(500); //谁执行我sleep代码就睡眠谁 睡眠的是自定义线程
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
//getName();获取当前执行run方法线程的名字。
System.out.println(this.getName()+":"+i);
//获取自定义线程对象
//Thread.currentThread()指的是执行run方法的对象。// d对象在执行run方法
System.out.println("当前线程对象"+Thread.currentThread());
System.out.println("this对象:"+this);
}
}
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
//创建线程时给他指定名字
Demo3 d = new Demo3("张三");
//设置名字
d.setName("老王");
//开启线程
d.start();
//Thread.sleep(500); //主线程在执行 , 睡眠的是主线程。
System.out.println("d============"+d);
//获取当前线程对象(主线程)
Thread maintT = Thread.currentThread();
System.out.println("当前线程对象:"+Thread.currentThread());
System.out.println("获取主线程的优先级:"+maintT.getPriority());
}
}
java给线程加锁 :
锁对象可以是任意一个java中的对象
java中的任意一个对象 都会有一个对象的状态 ,就可以通过对象的状态来作为锁的一个标识符。
statue = 0表示锁是关闭statue = 1表示锁打开。
synchronized (锁对象) {
}
同步代码块的使用注意点:
1.任意一个对象都可以做锁对象
2.如果你在同步代码块中调用了sleep方法 ,不会释放锁对象
3.只有真正存在线程安全的时候才需要使用同步代码块,否则会降低执行效率
4.多线程操作锁对象必须是唯一的 ,否则无效
思考:出现线程安全的问题根本原因:
1.存在两个或两个以上的线程。并且线程之间共享着一个资源。
2.多个语句操作了共享资源
知识点三:线程的通讯
线程的通讯:一个线程完成自己的任务,去通知另外一个线程去完成另外一个任务。
wait();等待 如果线程执行了wait方法 ,那么该线程就会处于一个等待状态,等待状态的线程必须要通过其他线程来调用
notify()方法来唤醒。
notify();唤醒 随机唤醒线程池中的一个线程。
notifyAll();唤醒所有等待的线程
生产者和消费者。
wait和notify的使用注意点 :
1.wait方法和notify方法是属性Object对象
2.wait方法和notify方法必须在同步线程中执行
3.wait方法和notify方法必须有锁对象来调用
网友评论