这几天复习多线程,
说到线程,就要说到进程,进程是什么,打开任务管理器,就可以看到进行中的程序
线程是进程内的执行单元,同一个进程又可以执行多个任务,而每一个任务,可以看成是一个线程
单线程:程序只有一条执行路径
多线程:程序执行多条路径
有了多线程的存在,不是提高了程序的执行速度,其实是为了提交应用程序的使用
程序的执行其实都是在抢CPU的资源,CPU的执行权
多个进程是在抢这个资源,而其中的某一个进程如果执行路径比较多,就会有更高的几率抢到资源
无法保证哪个线程先抢到,所以线程具有随机性
------------------------------
并行和并发的区别:
前者是逻辑上同时发生,指在某一个时间内同时运行多个程序。
后者是物理上发生的,指在某一个时间点同时运行多个程序。
-------------------------------
jvm虚拟机的启动是单线程的还是多线程
多线程的。
原因是垃圾回收线程也要先启动,否则很容易出现内存溢出
现在的垃圾回收线程加上前面的主线程,最低启动了两个线程
---------------------------------------
方式1:继承Thread类
步骤
A: 自定义类继承Thread类
B:MyThread 类里面重写run()方法
为什么run() 方法呢!
C:创建对象
D:启动线程
方式2:实现Runnable接口
步骤
A:自定义MyRunable类继承Runable类
B:重写run()方法
C:创建对象
创建MyR 实现类
创建Thread 对象。将MyR实现类作为参数传递到Thread对象中
D:启动线程
-------------------------------------------------------
方式1和方式二的区别:
1,方式2避免了单继承的局限性
2,适合多个程序,处理同一个资源对象,例如购票,能将数据有效的分离,比较好的体现了面对对象的设计
--------------------------------------------------------
多线程的同步代码机制
多线程同步代码三种简单方式:
1,同步代码快
将同步关键字加到Synchronized(Object) 加到 线程执行的程序上,并设置对象锁,锁必须是同一个
2,同步方法
将同步关关键字 Synchronized 将到方法体的修饰符后面,锁对象为this,本对象
3,同步静态代码块
将同步关键字Synchronized
静态方法同步锁对象 类的字节码文件,class文件,
----------------------------------------------------
线程安全的一些集合:
StringBuffer--Vetor---HashTable 打开源码都可以看到synchronized关键字
如果想创建安全的集合,也可以用Collections工具创建,里面有synchronized的方法
-----------------------------------------------------
以前遇到的问题:
同步方法与静态方法的锁对象往哪儿放
run() 和 start() 方法的区别;
run()--
--- 用来存在线程执行的代码,是一个普通的方法,如果单独被调用!
start()--
---通过线程启动start() 方法,线程通过jvm直接调用run()方法!用来启动线程
多线程执行的顺序:
新建--就绪--运行--死亡
新建--就绪--阻塞--运行--死亡
--------------------------------------------------
Lock 锁 在jdk5 之后 能够更能看清楚,在哪儿上的锁!
---------------------------------------------------
死锁问题--两个线程在抢夺资源的同时,同时等待!
--生产者和消费者的1问题
用的锁必须是同一对象!
等待和唤醒机制--wait() 等待 和 notify()唤醒
代码:
Student:
public class Student {
private String name;
private int age;
public static boolean flag;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
Astudent:
public class AStudent implements Runnable {
Student s;
public AStudent(Student s) {
this.s=s;
}
int x=0;
@Override
public void run() {
while(true){
synchronized(s){
if(s.flag){
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(x%2 == 0){
s.setName("曹展");
s.setAge(12);
}else{
s.setName("侯亚非");
s.setAge(15);
}
x++;
s.flag=true;
s.notify();
}
}
}
}
Bstudent:
public class BStudent implements Runnable{
Student s;
public BStudent(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.getAge()+"=="+s.getName());
s.flag=false;
s.notify();
}
}
}
}
测试代码演示:
public static void main(String[] args) {
Student s = new Student();
AStudent as = new AStudent(s);
BStudent bs = new BStudent(s);
Thread t1 = new Thread(as);
Thread t2 = new Thread(bs);
t1.start();
t2.start();
}
演示结果:
一个一个!生产一个,消费一个!
---------------------------------------------------
线程池:
--线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。提高线程使用效率!
Callable-- 第三种实现线程的方法,但是必须依赖线程池,并且可以返回值!
简单代码实现:
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"==="+i);
}
}
}
------------------------------------------------
public static void main(String[] args) {
//创建线程池,控制要几个线程
ExecutorService exce = Executors.newFixedThreadPool(2);
MyCallable mc1 = new MyCallable();
MyCallable mc2 =new MyCallable();
exce.submit(mc1);
exce.submit(mc2);;
//关掉线程池
exce.shutdown();
线程组:我觉得作用对于现在我并不是很大,就是把线程分到一个组中。
匿名内部类方式使用多线程:
--代码简单实现:
package com.sxjyatc.neiming;
public class DemoThread {
public static void main(String[] args) {
new Thread(){
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"hello"+"==="+i);
}
}
}.start();
new Thread(){
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"world"+"==="+i);
}
}
}.start();
new Thread(new Runnable() {
//会运行System.out.println(Thread.currentThread().getName()+"hel2lo"+"==="+i); --线程 main
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"world"+"==="+i);
}
}
});{
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName()+"hel2lo"+"==="+i);
}
};
}
}
定时器Time和TimeTask这两个类---可以定时刷新!
可以定时刷新,但是不稳定!