java学习笔记之初识多线程
Posted 猿上生活
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java学习笔记之初识多线程相关的知识,希望对你有一定的参考价值。
初识多线程
一.进程的认识:
1.进程的理解:
进程可以理解成正在执行的任务,就是正在运行的程序,进程又分为两种,一种是前台进程,就是我们很直观看见的,另一种是后台进程,就是操作系统启动就有的(系统级的进程),每个进程运行之后都会占用一定的cpu和内存资源;
比如说:我们打开window任务管理器就可以看到有很多的进程,里面有用户开启的,也有操作系统启动的进程
2.进程的调度:
也就是那么多的进程,cpu是怎样运行的呢?
采用时间片轮转法
二.线程认识
1.线程的理解
线程是在进程的内部运行的执行体
(1).一个进程可以创建多个线程
(2).进程和线程共同来争夺cpu,而且概率是均等的
(3).线程依赖进程,不能独立存在
(4).在java中,一个进程至少有一个线程,main方法被称为主线程;
我们可以在java的main方法中输出一个1/0;
(5).进程或者线程都有优先级,优先级高的可以得到更多的时间片和cpu的执行权
(6).抢占式调度:优先级高的进程可以抢占优先级低的cpu执行权
2.为什么要搞多线程?
原因:
(1).让多个程序同时执行
(2).提高程序的执行效率
三.线程的创建
1.方式一:继承Thread类
小demo:
1 //定义一个类,继承Thread类 2 public class MyThread extends Thread { 3 4 //重写Thread类的run方法 5 public void run(){ 6 System.out.print("我是一个子线程"); 7 } 8 }
1 public class Demo { 2 public static void main(String[] args) { 3 //创建子类对象,然后调用start();方法 4 MyThread mt=new MyThread(); 5 mt.start(); 6 } 7 }
2.方式二:实现Runnable接口
小demo:
//实现类的定义 public class MyRunnableImpl implements Runnable { //定义一个Runnable实现类,然后重写run方法 @Override public void run() { //这里写功能代码 } }
1 public class Demo { 2 //使用代码 3 public static void main(String[] args) { 4 //new 一个Runnable实现类对象 5 MyRunnableImpl my=new MyRunnableImpl(); 6 //然后将该实现类对象,传入Thread类的构造方法中,并创建Thread类对象 7 //调用Thread对象start()方法开启线程 8 new Thread(my).start(); 9 } 10 }
3.关于线程的一些方法使用
1 public class Demo { 2 public static void main(String[] args) { 3 /* 4 * 设置线程的名字:方法一 5 * 1.通过Thread 类的setName(String name)方法 6 */ 7 MyThread mThread=new MyThread();
mThread.setName("线程名字"); 8 mThread.start(); 9 /* 10 * 设置线程名字:方法二 11 * 2.通过Thread的构造方法 12 * Thread(Runnable r,String name); 13 */ 14 //创建Runnable实现类的对象 15 MyRunnable mr=new MyRunnable(); 16 new Thread(mr,"线程名称").start(); 17 18 } 19 }
1 public class MyThread extends Thread { 2 public void run(){ 3 /* 4 * 获取线程的名字的方法 5 * 1.通过Thread类的getName()方法 6 * 7 * 2.通过Thread类的静态方法currentThread()获取正在当前线程的对象 8 * 然后通过getName(),获得线程名称 9 */ 10 System.out.println("方法一线程的名字是:"+getName()); 11 System.out.println("方法二线程的名字是:"+Thread.currentThread().getName()); 12 } 13 }
四.线程的安全
1.线程安全问题产生的原因:
当多个线程去访问共享资源时候,就会发生线程安全问题
先看一个案例:多窗口卖电影票的案例
1 class Ticket implements Runnable { 2 //电影票的数量 3 private static int ticket=100; 4 @Override 5 public void run() { 6 while(true){ 7 if(ticket>0){ 8 //模拟网络延时的场景 9 try { 10 Thread.sleep(50); 11 } catch (InterruptedException e) { 12 // TODO Auto-generated catch block 13 e.printStackTrace(); 14 } 15 //对票数进行出售(减减操作) 16 System.out.println("正在售出第"+ticket--+"张票"); 17 } 18 } 19 } 20 } 21 public class Demo { 22 public static void main(String[] args) { 23 //new 一个实现类对象 24 Ticket t=new Ticket(); 25 //创建3个线程对电影票进行售卖 26 new Thread(t).start(); 27 new Thread(t).start(); 28 new Thread(t).start(); 29 30 } 31 }
这时候就出现了问题:
出现这个问题的解释:
当拥还剩一张电影票的时候,拥有cpu执行权的线程运行到while(true)的时候,顺利通过,然后在运行sleep();这时候这个线程进入堵塞状态,电影票还是1,cpu的执行权被另一个线程拿到,也正好运行到while(true),顺利通过,然后在运行sleep();cpu执行权被第三个线程抢去,同样的运行,到最后醒过来的线程会继续执行下面的代码。就产生了负数票的现象
2.线程安全问题的解决方案:
(1).同步代码块
1 2 //定义一个对象,当做锁对象 3 static Object obj = new Object(); 4 /* 5 同步代码块: 6 参数:锁对象 7 1:java任何对象都可以作为锁对象 8 2:所有的线程都必须共享这个锁对象(该对象只有一份) 9 synchronized(mutex){ 10 //存放需要加锁的代码 11 } 12 */ 13 14 //实现卖票的代码 15 @Override 16 public void run() { 17 18 while(true){ 19 synchronized (obj) {//加锁 20 if(tickets > 0 ){ 21 //模拟一个网络的延时 22 try{Thread.sleep(50);}catch(Exception e){} 23 System.out.println("正在出售第"+ tickets-- + "张票"); 24 } 25 }//解锁 26 } 27 }
(2).同步方法
1 /* 2 * 同步方法:对整个方法加锁 3 * 4 * 1:同步方法的锁对象是this, 这里的this必须是同一个 5 * 2:静态方法的锁对象是:类名.class 6 */ 7 /* 8 * 同步代码块和同步方法的区别: 9 * 1:同步代码块可以对任何一段代码进行加锁 10 * 2:同步方法是对整个方法都进行加锁 11 * 12 * 13 * 3:同步代码块的对象可以自己指定 14 * 4:同步方法的锁对象必须是this 15 */ 16 public synchronized void method(){ 17 if (tickets > 0) { 18 // 模拟一个网络的延时 19 try { 20 Thread.sleep(50); 21 } catch (Exception e) { 22 } 23 System.out.println("正在出售第" + tickets-- + "张票"); 24 } 25 } 26 27 // 实现卖票的代码 28 @Override 29 public void run() { 30 31 while (true) { 32 method(); 33 } 34 }
(3).同步锁
1 /* 2 * 同步锁: 3 * Lock接口: 4 * ReentrantLock实现类: 5 * lock(); 加锁 6 * unlock();解锁 7 */ 8 9 //1:创建锁对象 10 ReentrantLock rt = new ReentrantLock(); 11 12 13 // 实现卖票的代码 14 @Override 15 public void run() { 16 17 while (true) { 18 //2:在适当的地方加锁 19 rt.lock(); 20 21 if (tickets > 0) { 22 // 模拟一个网络的延时 23 try { 24 Thread.sleep(50); 25 } catch (Exception e) { 26 } 27 System.out.println("正在出售第" + tickets-- + "张票"); 28 } 29 //3:在适当的地方解锁 30 rt.unlock(); 31 } 32 }
五.线程的状态
以上是关于java学习笔记之初识多线程的主要内容,如果未能解决你的问题,请参考以下文章