#上课笔记,仅自己看得懂:
一 并行和并发
/*
- 并行:事件在同一时刻发生
- 并发:事件在同一时间(段)间隔发生
-
- 并发:
- 1)单核:执行单个
- 2)多核:同时执行多个-》并行
- 利用每一个处理机处理并发的程序-》同时执行——》并行
- -》同理,线程也一样,宏观上是并行,微观上是串型
- 当单cpu时,通过线程调度完成任务,
- 要解决多个程序并发操作-》进程和线程
*/
二,进程和线程
/*
- 进程:
- 一个内存中运行的应用程序
- 程序可一同时启动多个进程
- XX.exe就是一个进程
- 大多数的操作系统都不需要一个进程去访问其他进程的内存空间,
*也就是通信很不方便
*引出技术-》线程解决
*线程指的是进程中一个执行任务的控制单元,一个进程可一同时并发多个线程
*比如:多线程下载软件
*进程:有独立的空间,进程中的数据存放空间(堆和栈空间)至少有一个线程
*
*线程;堆空间共享,栈空间独立,线程消耗的资源也比进程小
*------------------------------------------------
*因为一个进程的多个线程是并发运行的,
*从微观角度来看也是有先后顺序的,但是具体先运行
*哪个线程由调度决定,即多线程的随机性
*Java程序的进程至少包含主线程和垃圾回收线程
*-------------------------------------
*多线程优势:
*
*提高应用程序的相应
*使多cpu更加有效
*改善程序结构
*/
/*线程之间可以相互影响
* 多线程之间是 《 并发 》 运行
* start启动而不是run
* 线程,堆共享,消耗资源少
* 内存:
* jvm GC垃圾回收机制
*线程一般推荐使用接口实现方式
*/
三.创建和启动线程的方式
1) 继承Thread类
2) 实现runnable接口
3) 使用匿名内部类,
继承:
/* 1)继承Thread类
* 自定义music类,使其继承Thread类
* 让music类覆盖Thread的run方法
* 在main方法中创建music的对象,并启动
* ---------------------------------
* 调用线程方法用start,开一个线程
*/
class MusicThrea extends java.lang.Thread {
public void run() {
super.run();
for(int i=0;i<50;i++) {
System.out.println("listen music "+i);
}
}
}
class hardStudyThrea extends java.lang.Thread {
public void run() {
super.run();
for(int i=0;i<50;i++) {
System.out.println("hardStudy "+i);
}
}
}
//播放音乐的线程类
public class EctendsDemo {
public static void main(String [] args) {
new MusicThrea().start();
new hardStudyThrea().start();
for(int i=0;i<50;i++){
System.out.println("play game"+i);
}
}
}
实现:
/*自定义,music类,实现runnable接口
* 让music类覆盖runnable类中的run方法,
* 在main方法中定义另外一个要执行的代码
* 在main方法中启动
*/
class musicRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 50; i++) {
System.out.println("listen music " + i);
}
}
}
//实现runnable接口
public class ImpelementDemo {
public static void main(String[] args) {
System.out.println("begin....");
for (int i = 0; i < 50; i++) {
System.out.println("play game" + i);
if (i == 10) {
new Thread(new musicRunnable()).start();
}
}
}
}
匿名内部:(也有三种写法,这里只有lambda和一种叫“我也不知道叫什么”的写法)
import java.nio.channels.NonWritableChannelException;
import javax.xml.stream.events.StartDocument;
//使用匿名内部类
public class InnerDemo {
public static void main(String[] args) {
text1();
text3();
}
private static void text3() {// lambda写法
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
System.out.println("play music"+i);
if(i==10) {
//create Thread to start
new Thread(()->{
for(int j=0;j<50;j++) {
System.out.println("play game"+j);
}
}).start();
}
}
}
private static void text1() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
System.out.println("play game"+i);
if(i==10) {
new Thread() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
System.out.println("listen music "+i);
}
}
}.start();
}
}
}
}
PK:继承和实现的对比
推荐实现这个方式,继承容易出问题,而且Java只支持单继承,如果用继承,那它今后就没办法继承其他的了
实现比较灵活耦合度又比较好控制
四,解决线程的不安全问题
Synchonized和Lock()
关于synchonized:
/* synchonized public 返回类型 方法名(参数列表){
* 需要同步的代码
* }
*
* 好处:
* 避免啦多线程安全问题
* 坏处:
* 性能上比不用要低一些
* 尽量减少synchronized的作用域
*/
/*
* 对对象标记一个锁
* 谁拿到锁就进入代码块,其他线程只能在外面等着
* 原子操作:不能分割,保证同步运行
*/
class appl2 implements Runnable{
private Integer nums=50;
synchronized public void eat() {
if(nums>0) {
System.out.println(Thread.currentThread().getName()+" get "+nums);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
nums--;
}
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<50;i++) {
eat();
}
}
}
public class syn {
public static void main(String[] args) {
appl2 apple=new appl2();
//new Thread(apple,"A").start();
new Thread(apple,"B").start();
new Thread(apple,"C").start();
}
}
Lock():
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class appl implements Runnable{
private Integer nums=50;
private final Lock lock=new ReentrantLock();
//ReentrantLock()可重入的互斥锁
public void eat() {
lock.lock();
if(nums>0) {
try { System.out.println(Thread.currentThread().getName()+" get "+nums);
nums--;
Thread.sleep(100);
//让当前线程先休眠,
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
lock.unlock();
}
}
}
@Override
public void run() {
for(int i=0;i<50;i++) {
eat();
}
}
}
public class Synchron {
/*
* 同步代码块
*/
public static void main(String[] args) {
appl apple=new appl();
new Thread(apple,"A").start();
new Thread(apple,"B").start();
new Thread(apple,"C").start();
/*
*lock机制比synchronized更加强大,功能更多,关键是灵活啊,作用域范围比较容易控制
*更加面向对象
*步骤:
*创建锁
*需要的同步方法,获取锁,加锁
*解锁
*/
}}