进程与线程
线程与进程相似,是一段完成某个特定功能的代 码,是程序中单个顺序控制的流程,但与进程不同 的是,同类的多个线程是共享一块内存空间和一组 系统资源。所以系统在各个线程之间切换时,开销 要比进程小的多,正因如此,线程被称为轻量级进程。一个进程中可以包含多个线程。
- 进程相当于软件有独立内存空间
- 线程相当于软件的执行路径
- 一个软件可以有多个执行路径即进程包含多个线程
- -每个线程都有自己的栈空间,共享一份堆内存
线程有同步与异步、高效与低效、安全与不安全
并发与并行(并发:同一段时间 并行:同一时刻)
线程创建
Java中创建一个子线程涉及到:java.lang.Thread类 和java.lang.Runnable接口
Thread是线程类,创建 一个Thread对象就会产生一个新的线程。而线程执 行的程序代码是在实现Runnable接口对象的run()方 法中编写的,实现Runnable接口对象是线程执行对 象。
线程执行对象实现Runnable接口的run()方法,run() 方法是线程执行的入口,该线程要执行程序代码都 在此编写的,run()方法称为线程体。
//接口Runnanle
public interface Runnable {
public abstract void run();
}
//接口实现
public class Thread implements Runnable{}
//
public class MyThread extends Thread{}
继承Thread线程类
Thread类
构造方法
Thread()
Thread(Runnable target)
Thread(Runnable target, String name)
常用方法
getName()//String
getPriority()//int
setPriority(int newPriority)//void
start()
stop()//不安全过时
sleep(long millis, int nanos)
setDaemon(boolean on)
Thread继承实例
public class DemoThread {
public static void main(String[] args) {
//Thread线程类
//创建线程
MyThread m = new MyThread();
//开始线程
m.start();
}
}
子类
//线程执行对象
/*run方法就是线程要执行的任务方法
*/
public class MyThread extends Thread {
//这里的代码 就是一条新的执行路径
//这个执行路径的触发方式不是调用run方法,而是通过thread对象的start()来启动任务
@Override
public void run() {
for(int i = 0;i<10;i++){
System.out.println("lllllll");
}
}
}
//Thread可以用来当匿名内部类
new Thread(){
@Override
public void run() {
super.run();
}
}.start();
接口Runnable的实现
创建线程Thread对象时,可以将线程执行对象传递 给它
public class DemoRunnable {
public static void main(String[] args) {
//实现Runnable
/*//1. 创建一个任务对象
MyRunnable m = new MyRunnable();
//2. 创建一个线程,并为其分配一个任务
Thread t = new Thread(m);
*/
Thread t = new Thread(new MyRunnable());
//3. 执行
t.start();
}
}
实现类
public class MyRunnable implements Runnable {
@Override
public void run() {
//线程的任务
for(int i = 0;i<10;i++){
System.out.println("jiaijs");
}
}
}
实现Runnable 与继成Thread有如下优势:
- 1.通过创建任务给线程分配的方式来实现多线程,更适合多个线程同时执行相同任务的情况
- 2.可以避免单继承带来的局限性
- 3.任务与线程本身是分离的,提高程序的健壮性
- 4.后续学习的线程池技术,只接受Runnable类型的任务
获取设置线程名
public static void main(String[] args) throws InterruptedException {
//获取线程名称
System.out.println(Thread.currentThread().getName());
//new Thread(new MRunnable()).start();
Thread t = new Thread(new MRunnable());
t.setName("线程");
t.start();
}
static class MRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
线程的休眠 sleep
Thread.sleep(1000);
线程中断
//线程的休眠 sleep
Thread.sleep(1000);
//线程阻塞/耗时操作
//线程中断stop过时
//一个线程是一个独立的执行路径,他是否应该结束,应该由其自身结束
Thread t1 = new Thread(new MRunnable());
t1.start();
for (int i = 0;i<10;i++){
System.out.println(Thread.currentThread().getName()+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//给线程t1做中断标记
t1.interrupt();
}
static class MRunnable implements Runnable{
@Override
public void run() {
for (int i = 0;i<10;i++){
System.out.println(Thread.currentThread().getName()+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// e.printStackTrace();
System.out.println("发现中断标记");
return;//表示自杀
}
}
}
}
线程:用户线程和守护线程
//我们创建的就是用户线程
//用户线程当一个进程不包含任何存活的用户线程时,进程结束
// 守护线程用于守护用户线程的,当最后一个用户线程结束时,所有守护线程自动死亡
//将用户线程转化为守护线程 比如子线程要在start之前转化
//t1.setDaemon(true);
线程安全
线程不安全
public static void main(String[] args) {
//线程不安全问题
Runnable r = new Ticket();//多态
new Thread(r).run();
new Thread(r).run();
new Thread(r).run();
}
static class Ticket implements Runnable{
private int count = 10;
@Override
public void run() {
while(count>0){
System.out.println("正在出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println("剩余:"+count);
}
}
}
解决方案
//线程同步:synchronized
public class DemoSynchronized {
public static void main(String[] args) {
//线程不安全
//解决方案1:同步代码块
///格式:synchronized(锁对象){}
Runnable r = new DemoThreadSafe.Ticket();//多态
new Thread(r).run();
new Thread(r).run();
new Thread(r).run();
}
static class Ticket implements Runnable{
private int count = 10;
private Object o = new Object();
@Override
public void run() {
while(true) {
// private Object o = new Object();加这里相当于每人一把锁同步代码块就没用了
synchronized (o) {
if (count > 0) {
System.out.println("正在出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"剩余:" + count);
}else{
break;
}
}
}
}
}
}
public class DemoThreadSafe2 {
public static void main(String[] args) {
//2.同步方法代码块
Runnable r = new DemoThreadSafe.Ticket();//多态
new Thread(r).run();
new Thread(r).run();
new Thread(r).run();
}
static class Ticket implements Runnable{
private int count = 10;
//显示锁l:fair参数为true为公平锁
private Lock l = new ReentrantLock(true);
@Override
public void run() {
while(true) {
boolean flag = sale();
if(!flag){
break;
}
}
}
public synchronized boolean sale(){
//锁修饰的方法,锁的是调用它的对象this
//如果是静态的方法就是 类.calss 即Ticket.class
if (count > 0) {
System.out.println("正在出票");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
count--;
System.out.println(Thread.currentThread().getName()+"剩余:" + count);
return true;
}
return false;
}
}
}
死锁问题
public class DemoThreadDeath {
public static void main(String[] args) {
Culprit c = new Culprit();
Police p =new Police();
new MyThread(c,p).start();
c.say(p);
}
static class MyThread extends Thread{
private Culprit c;
private Police p;
public MyThread(Culprit c,Police p){
this.c = c;
this.p = p;
}
@Override
public void run() {
p.say(c);
}
}
static class Culprit{
public synchronized void say(Police p){
System.out.println("你放了我,我放了人质");
p.fun();
}
public synchronized void fun(){
System.out.println("罪犯放走人质,罪犯也放走了");
}
}
static class Police{
public synchronized void say(Culprit c){
System.out.println("你放了人质,我放了你");
c.fun();
}
public synchronized void fun(){
System.out.println("警察救了人质,罪犯跑了");
}
}
}
多线程通讯问题
public class DemoWait {
//多线程通讯问题,生产者与消费者的问题
public static void main(String[] args) {
Food f = new Food();
new Cook(f).start();
new Waiter(f).start();
}
static class Cook extends Thread{
private Food f;
public Cook (Food f) {
this.f = f;
}
@Override
public void run() {
for(int i =0;i<100;i++){
if(i%2==0){
f.setNameTaste("1","a");
}else {
f.setNameTaste("2","b");
}
}
}
}
static class Waiter extends Thread{
private Food f;
public Waiter (Food f){
this.f= f;
}
public void run() {
for(int i =0;i<100;i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
f.get();
}
}
}
static class Food{
private String name;
private String taste;
private boolean flag = true;
public void setNameTaste(String name, String taste) {
if(flag) {
this.name = name;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.taste = taste;
flag=false;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void get(){
if(!flag) {
System.out.println("服务员端菜" + name + taste);
}
flag = true;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}