1.4.1并发和并行
并行:指两个或多个事件在同一时刻发生(同时执行)
并发:指两个或多个事件在同一时间段内发生(交替执行)
1.4.2进程和线程
一.进程
进程(process)是指正在运行的程序。如QQ,是程序一次动态执行的过程。它对应了从代码加载、执行并执行完 毕的一个完整过程,这个过程也是进程本身从产生、发展到消亡的过程。操作系统同时管理一个计算机系统中的多个进程,让计算机系统中的多个进程轮流使用CPU资源,或者共享资源。
特点:
进程是系统运行的基本单位每一个进程都有自己独立的空间、一组系统资源每一个进程内部数据和状态都是完全独立的每一个应用程序运行时都会产生一个进程
二、线程
线程是进程中执行运算的最小单位,一个进程在其执行过程中可以产生多个线程,而线程必须在某个进程内执行。
线程是进程内部的一个执行单元,是完成一个独立任务的顺序控制流程。一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以叫做多线程程序。
三、进程和线程的区别
进程:有独立的内存空间,进程中的数据存放空间(栈空间和堆空间)是独立的,至少有一个线程。
线程:堆空间是共享的,占空间是独立的,线程消耗的资源比进程小得多
3.多线程和多进程的区别
本质的区别在于每个进程拥有自己的一套变量,而线程则是共享数据。线程之间共享数据是有风险的。然而共享变量使线程之间的通信比进程之间通信更有效,、更容易。此外,在有的操作系统中,与进程相比,线程更轻量级,创建、撤销一个线程比启动新的进程开销要小得多。
线程调度
1.分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间
2.抢占式调度:优先让优先级高的线程使用cpu,如果线程的优先级相同,那么会随机选择一个(线程随机性),java使用的是抢占式调度
4.创建线程类
每个程序至少自动又有一个线程,称为主线程。当程序加载到内存时启动主线程。main方法是主线程的入口,运行java程序时会指向这个方法
常见一个新的执行线程有两种方法,一个是将类声明为Thread的子类。这个子类应该重写Thread的子类Run。然后就可以分配并启动Thread的子类。
一、使用Thread类
java.lang.Thread类代表线程。每个线程的作用是完成一定的任务,实际上就是执行一段程序流即一段顺序执行的代码。java使用线程执行体来代表这段程序流。
package cn
.itlaobing
.zeyu
;
public class MyThread extends Thread {
public MyThread(String mythread
) {
super(mythread
);
}
@Override
public void run() {
for (int i
=0;i
<200;i
++){
System
.out
.println(getName()+":正在执行"+i
);
try {
Thread
.sleep(50);
} catch (InterruptedException e
) {
e
.printStackTrace();
}
}
}
}
package cn
.itlaobing
.zeyu
;
public class ThreadTest {
public static void main(String
[] args
) throws InterruptedException
{
MyThread myThread
= new MyThread("Mythread");
myThread
.start();
for (int i
=0;i
<200;i
++){
System
.out
.println("主线程--正在执行"+i
);
Thread
.sleep(50);
}
}
}
常用的构造方法:
public Thread()
public Thread(String name)
public Thread(Runnable Target
)
public Thread(Runnable Target,String name
)
二、线程Thread的属性(Fields)
public static final int MIN_PRIORITY
= 1;
public static final int NORM_PRIORITY
= 5;
public static final int MAX_PRIORITY
= 10;
三、线程Thread的常用方法
public static Thread
currentThread() 返回对当前正在执行的线程对象的引用。
public void run()
public void start()
public static native void sleep(long millis
)
public final String
getName()
public final void setName(String name
)
public final void setPriority(int newPriority
)
public final int getPriority()
public final boolean isAlive()
public final void join()
public final void join(long millis
)
public static boolean interrupted()
public Thread
.State
getState()
四、使用接口的方式创建
java.lang.Runnable 也是非常常见的一种创建线程的方式,我们只需要重写run方法即可。任何实现Runnable 的类,其实例都能被线程执行。
package cn
.itlaobing
.zeyu
;
public class RunnableTest implements Runnable {
@Override
public void run() {
for (int i
=0;i
<500;i
++){
System
.out
.println(Thread
.currentThread().getName()+" "+i
);
}
}
}
package cn
.itlaobing
.zeyu
;
public class ThreadTest {
public static void main(String
[] args
) throws InterruptedException
{
RunnableTest runnableTest
= new RunnableTest();
Thread thread
= new Thread(runnableTest
);
thread
.start();
for (int i
=0;i
<500;i
++){
System
.out
.println("主线程--正在执行"+i
);
}
}
}
五、Thread和Runnable区别
1.适合多个相同的程序代码的线程去共享同一个资源
2.可以避免java中的单继承的局现性
3.增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立
4.实现了Runnable接口的话,很容易的实现资源共享(一个实例多个线程运行)
5.线程池只能放入实现Runnable或callable类线程,不能直接放入继承Thread的类
5.线程安全问题
package com
.itlaobing
.zeyu
;
public class TicketTest {
public static void main(String
[] args
) {
Ticket ticket
= new Ticket();
Thread thread1
= new Thread(ticket
,"窗口1");
Thread thread2
= new Thread(ticket
,"窗口2");
Thread thread3
= new Thread(ticket
,"窗口3");
thread1
.start();
thread2
.start();
thread3
.start();
}
}
package com
.itlaobing
.zeyu
;
public class Ticket implements Runnable {
private int tickets
= 100;
Object o
= new Object();
@Override
public void run() {
while (true){
synchronized (o
){
if (tickets
>0){
try {
Thread
.sleep(200);
} catch (InterruptedException e
) {
e
.printStackTrace();
}
String name
= Thread
.currentThread().getName();
System
.out
.println("正在售卖第"+tickets
--+"张票");
}else {
break;
}
}
}
}
}
@Override
public void run() {
while (true){
sellTickets();
}
}
private synchronized void sellTickets() {
if (tickets
>0){
try {
Thread
.sleep(200);
} catch (InterruptedException e
) {
e
.printStackTrace();
}
String name
= Thread
.currentThread().getName();
System
.out
.println("正在售卖第"+tickets
--+"张票");
}
}
private Lock lock
= new ReentrantLock();
@Override
public void run() {
while (true){
lock
.lock();
sellTickets();
lock
.unlock();
}
}
private synchronized void sellTickets() {
if (tickets
>0){
try {
Thread
.sleep(200);
} catch (InterruptedException e
) {
e
.printStackTrace();
}
String name
= Thread
.currentThread().getName();
System
.out
.println(Thread
.currentThread().getName()+"正在售卖第"+tickets
--+"张票");
}
}
6.生产者和消费者
/*
面包-- 制作,吃的方法
name-->面包的名字,用时间表示
cook对象只有一个,全程代码中只有这个对象的引用
*/
package com.itlaobing.zeyu;
import java.time.LocalDateTime;
public class Cook {
//面包
private String name;
private Cook(){}
private static Cook cook;
public synchronized static Cook getInstance(){
if(cook==null){
cook = new Cook();
}
return cook;
}
public synchronized void make() throws InterruptedException {
if (name!=null){
wait();
}
name = "豆沙包" + LocalDateTime.now().toString();
System.out.println(Thread.currentThread().getName()+"做了一个面包" + name);
notifyAll();
}
public synchronized void eat() throws InterruptedException {
if (name==null){
wait();
eat();
return;
}
System.out.println(Thread.currentThread().getName()+"吃了一个:"+name);
name = null;
notifyAll();
}
}
--------------------------------------------------------------------------------------
/*
做面包的线程
*/
package com.itlaobing.zeyu;
public class MakeThread implements Runnable {
private Cook cook;
public MakeThread(Cook cook){
this.cook = cook;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
cook.make();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
--------------------------------------------------------------------------------------
/*
吃面包的线程
*/
package com.itlaobing.zeyu;
public class EatThread implements Runnable {
private Cook cook;
public EatThread(Cook cook){
this.cook = cook;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
cook.eat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
----------------------------------------------------------------------------------------
/*
测试类
*/
package com.itlaobing.zeyu;
public class CookTest {
public static void main(String[] args) throws InterruptedException {
Cook cook = Cook.getInstance();
MakeThread makeThread = new MakeThread(cook);
EatThread eatThread = new EatThread(cook);
Thread thread1 = new Thread(makeThread,"zeyu" );
Thread thread2 = new Thread(eatThread,"浪老师");
Thread thread3 = new Thread(eatThread,"红雨老师");
thread1.start();
thread2.start();
thread3.start();
// while (true){
// System.out.println("make="+thread1.getState()+",eat="+thread2.getState()+"和"+thread3.getState());
// Thread.sleep(1000);
// }
}
}