Java基础(四)线程快速了解
开始整理线程之前,之前有个命令忘记整理了,先整理一下jar命令的使用
Jar包
其实可以理解是java的压缩包
方便使用,只要在classpath设置jar路径即可
数据库驱动,ssh框架等都是以jar包体现的
打包方式一:将指定的class文件打入到jar包中
jar cvf xxx.jar Xxx.class yyy.class
打包方式二:将某个目录下的所有文件打入到jar包中
jar cvf xxx.jar -C xxx/.
查看jar文件:
jar -tf xxx.jar
运行jar包中的类:
java -cp xxx.jar xx.xx.xx(完整的类名)
常用的jar命令参数:
c:创建压缩文件
f:指定存档名称
v:显示详细信息
m:加入自定义清单
指定清单文件(xxx.jar/META-INF/MNIFEST.MF)的入口类
jar cvfe classess.jar com.zhaofan.PackagDemo1 classes/.
这样我们就可以通过java -jar xxx.jar直接执行
线程
进程:运行时概念,运行的应用程序
线程:应用程序内部并发执行的代码段,共享内存
这里几个关键词
yield: 放弃cpu抢占权
join:等待指定的线程执行完
sleep:静态方法,让线程休眠毫秒数
daemo:守护线程
最简单的线程代码:
package study_java.ex9; public class ThreadDemo1 {
public static void main(String[] args){
Mythread t1 = new Mythread();
t1.start();
}
} class Mythread extends Thread{
public void run(){
while (true){
System.out.println("MyThread");
} }
}
join的一个简单实用例子:
package study_java.ex9; public class ThreadDemo2 {
public static void main(String[] args){
Player p1 = new Player("aa",5000);
Player p2 = new Player("bb",8000);
Player p3 = new Player("cc",2000);
Player p4 = new Player("dd",3000);
p1.start();
p2.start();
p3.start();
p4.start();
try{
p1.join();
p2.join();
p3.join();
p3.join();
}
catch (Exception e){ } System.out.println("人到了,开始玩游戏");
}
} class Player extends Thread{
private String name;
private int time;
public Player(String name, int time){
this.name = name;
this.time = time;
}
public void run(){
System.out.println("玩家:"+name + "出发了");
try{
Thread.sleep(time);
}
catch (Exception e){ }
System.out.println("玩家:"+name + "到了"); }
}
守护线程的一个使用例子
package study_java.ex9; import java.util.Date; public class ThraedDemo3 {
public static void main(String[] args){
Room r1 = new Room("no1",15000);
Waiter w1 = new Waiter();
//w1.setDaemon(true); 设置守护线程
r1.start();
w1.start();
}
} class Room extends Thread{
private String no;
private int time; public Room(String no, int time){
this.no = no;
this.time = time;
} public void run(){
System.out.println("no" + "号房间正在唱歌");
try{
Thread.sleep(time);
}
catch (Exception e){ }
System.out.println("no" + "买单");
}
} class Waiter extends Thread{
public Waiter(){
this.setDaemon(true);
}
public void run(){
while (true){
System.out.println(new java.util.Date());
try{
Thread.sleep(1000);
}
catch (Exception e){ }
}
}
}
任何一个对象都可以是锁,信号灯,其实就是一个参照物
一个锁的代码例子:
package study_java.ex9; public class ThreadDemo4 {
public static void main(String[] args){
Saler s1 = new Saler("a1");
Saler s2 = new Saler("a2");
s1.start();
s2.start();
}
} class Saler extends Thread{
// 锁
static Object lock = new Object(); static int tickts = 100;
private String name;
public Saler(String name){
this.name = name;
}
public void run(){
while (true){
int tick = getTickts();
if (tick > 0){
System.out.println(name+":"+ tick);
}
else {
return;
}
}
}
// 取票
public int getTickts(){
synchronized (lock){
int currTicket = tickts;
tickts --;
return currTicket;
}
}
}
还有一种方法是:
public static synchronized int getTickts(){
int currTicket = tickts;
tickts --;
return currTicket;
}
这样也能实现锁的机制,但是注意这里必须是static
我们整理一个新的写法,把票池单独写出来
public class ThreadDemo2 {
public static void main(String[] args){
TicketPool pool = new TicketPool();
Saler s1 = new Saler("s1",pool);
Saler s2 = new Saler("s2",pool);
s1.start();
s2.start();
}
} // 票池
class TicketPool {
private int tickets = 100;
// 从票池取票
public synchronized int getTickets(){
int ticket = tickets;
tickets -= 1;
return ticket;
}
}
// 售票员
class Saler extends Thread{
private TicketPool pool = null;
private String name;
public Saler(String name, TicketPool tp){
this.name = name;
this.pool = tp;
}
public void run(){
while (true){
int no = pool.getTickets();
if (no > 0 ){
System.out.println(name + ":" + no);
}
else {
return;
}
}
}
}
两个小的练习熟悉上面知识点的使用:
车过山洞的问题,山洞同时只允许一个车通过,现在有多辆车,不同的车通过的时间不同,代码实现如下:
package study_java.ex11; public class CarCave {
public static void main(String[] args){
Cave cave = new Cave();
Car car1 = new Car(cave,10000,"奥迪");
Car car2 = new Car(cave,8000,"奔驰");
Car car3 = new Car(cave,6000,"宝马");
Car car4 = new Car(cave,2000,"悍马");
car1.start();
car2.start();
car3.start();
car4.start(); }
} class Cave{ public synchronized void crossCar(Car car){
try{
System.out.println(car.name+":开始过山洞了");
Thread.sleep(car.time);
System.out.println(car.name+":开始出山洞了");
}
catch (Exception e){ } }
} class Car extends Thread{
public Cave cave;
public int time;
public String name; public Car(Cave cave ,int time,String name){
this.cave = cave;
this.time = time;
this.name = name;
}
public void run(){
cave.crossCar(this);
}
}
第二个小练习是我们经常遇到的场景,取票问题,现在有一个取票机,但是有五十个人要取票,实现代码如下:
package study_java.ex11; public class TicketDemo1 {
public static void main(String[] args){
TicketMachine m = new TicketMachine();
for (int i=0;i<50;i++){
new Person(m,"tom"+i).start();
}
}
} // 取票机
class TicketMachine{
private int ticketNo = 1;
// 打印票号
public synchronized int printTicktNo(){
int currTicketNo = ticketNo;
ticketNo ++;
return currTicketNo;
}
} class Person extends Thread{
private TicketMachine m;
private String name;
public Person(TicketMachine m,String name) {
this.m = m;
this.name = name;
}
public void run(){
int no = m.printTicktNo();
System.out.println(name+ ":" + no);
}
}
生产者消费者模型
通过上面的知识点,写一个生产者好消费者模型
package study_java.ex11; import java.util.LinkedList;
import java.util.List; public class PCDemo1 {
public static void main(String[] args){
MyList myList = new MyList(); Productor p = new Productor(myList);
Consumer c = new Consumer(myList);
Consumer c2 = new Consumer(myList);
Consumer c3 = new Consumer(myList);
p.start();
c.start();
c2.start();
c3.start();
} } class MyList{
private int Max = 100;
private List<Integer> list = new LinkedList<Integer>();
public void addLast(Integer i){
while (true){
synchronized (list){
if (list.size() < Max){
list.add(i);
return;
}
}
} }
public Integer removeFirst(){
while (true){
synchronized (list){
if(!list.isEmpty()){
return list.remove(0);
}
}
}
}
} class Productor extends Thread{
private MyList myList;
public Productor(MyList myList){
this.myList = myList;
}
public void run(){
int i = 1;
while (true){
myList.addLast(new Integer(i));
System.out.println("生产者生产了"+i+"号");
i++;
}
}
} class Consumer extends Thread{
private MyList myList;
public Consumer(MyList myList){
this.myList = myList;
}
public void run(){
while (true){
int no = myList.removeFirst();
System.out.println("消费者消费了"+no+"号");
}
}
}
生产者消费者而改进版本:
package study_java.ex11; import java.util.LinkedList;
import java.util.List; public class PCDemo5 {
public static void main(String[] args){
Pool pool = new Pool();
Producter p1 = new Producter(pool);
Consumer c1 = new Consumer(pool);
p1.start();
c1.start(); }
} class Pool{
private List<Integer> list = new LinkedList<Integer>();
private int Max = 100;
public void addLast(int n){
synchronized (this){
while (list.size() >= Max){
try{
this.wait();
}
catch (Exception e){
e.printStackTrace();
}
}
list.add(new Integer(n)); this.notifyAll();
}
}
public int remove(){
synchronized (this){
while (list.size() == 0){
try{
this.wait();
}
catch (Exception e){
e.printStackTrace();
} }
int no = list.remove(0); this.notifyAll();
return no;
}
} } // 生产者
class Producter extends Thread{
private Pool pool;
static int i = 1;
public Producter(Pool pool){
this.pool = pool;
}
public void run(){
while (true){
pool.addLast(i++);
System.out.println("生产者生产了"+i+"号");
}
} } // 消费者
class Consumer extends Thread{
private Pool pool;
public Consumer(Pool pool){
this.pool = pool;
}
public void run(){
while (true){
int no = pool.remove();
System.out.println("消费者消费了"+no+"号");
}
} }
wait():让当前线程进入到锁对象的等待队列里,同时释放锁旗标。这个方法是当前锁对象的方法
wait这里还可以添加参数wait(int n) :等待指定的时间片,等待队列中的线程最多等待n毫秒
notify():这个方法是当前锁对象的方法,注意这里并不会释放锁
notifyAll():通知等待队列中的所有线程都可以抢占cpu运行,通知需要获得对象的监控权
sleep:当前CPU的抢占权,和锁对象的监控权无关。
Thread.currentThread().getName():获取当前线程名字
Thread.currentThread().setName():设置当前线程名字
priority:1-10从低到高,默认是5
Thread.currentThread().getPriority():设置当前线程优先级
线程状态:
BLOCKED: 阻塞
NEW:新建
RUNNABL:执行
TERMINATED:已经终止
TIMED_WAITING:限时等待
WAITING:等待
创建一个线程的另外一种方式:
实现Runnable接口
1. 子类覆盖接口中的run方法
2. 通过Thread类创建线程,并将实现了Runnable接口的子类对象作为参数传递给Thread类的构造函数
3. Thread类对象调用start方法开启线程
代码例子如下:
package study_java.ex11; public class RunnableDemo1 {
public static void main(String[] args){
MyRunnabl m = new MyRunnabl();
new Thread(m).start();
}
} class MyRunnabl implements Runnable{
public void run(){
System.out.println("hello world");
}
}
同步(synchronized)
synchronized(对象)
{
需要同步的代码
}
同步的特点:
同步的前提是:
需要两个或者两个以上的线程
多个线程使用的同一个锁
同步的弊端:
当线程相当多时,因为每个线程都会去判断同步上的锁,这是很耗费资源的,无形中会降低程序的额运行效率
Java基础(四)线程快速了解的更多相关文章
- 重学JAVA基础(四):线程的创建与执行
1.继承Thread public class TestThread extends Thread{ public void run(){ System.out.println(Thread.curr ...
- Java基础(四) StringBuffer、StringBuilder原理浅析
StringBuilder与StringBuffer作用就是用来处理字符串,但String类本身也具备很多方法可以用来处理字符串,那么为什么还要引入这两个类呢? 关于String的讲解请看Java基础 ...
- 【Java基础】线程和并发机制
前言 在Java中,线程是一个很关键的名词,也是很高频使用的一种资源.那么它的概念是什么呢,是如何定义的,用法又有哪些呢?为何说Android里只有一个主线程呢,什么是工作线程呢.线程又存在并发,并发 ...
- Java基础-多线程-③线程同步之synchronized
使用线程同步解决多线程安全问题 上一篇 Java基础-多线程-②多线程的安全问题 中我们说到多线程可能引发的安全问题,原因在于多个线程共享了数据,且一个线程在操作(多为写操作)数据的过程中,另一个线程 ...
- java 基础 四种权限修饰符
/** * Java有四种权限修饰符: * public > protected > (default) > private * 同一个类 YES YES YES YES * 同一个 ...
- Java基础篇——线程、并发编程知识点全面介绍(面试、学习的必备索引)
原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10739579.html,希望大家多多支持!!! 一.线程基础 1.线程与进程 线程是指进程 ...
- Java基础(四)-异常处理机制及其设计
本篇主要是记录自己所理解的Java异常处理机制(基于jdk1.7)以及怎么去处理和设计异常.还记得当初学习Java异常这块的时候都没怎么注意它的用途,以为就是简单的处理下异常,我避免程序出现这样错误就 ...
- Java多线程(四) 线程池
一个优秀的软件不会随意的创建.销毁线程,因为创建和销毁线程需要耗费大量的CPU时间以及需要和内存做出大量的交互.因此JDK5提出了使用线程池,让程序员把更多的精力放在业务逻辑上面,弱化对线程的开闭管理 ...
- Java多线程(四) —— 线程并发库之Atomic
一.从原子操作开始 从相对简单的Atomic入手(java.util.concurrent是基于Queue的并发包,而Queue,很多情况下使用到了Atomic操作,因此首先从这里开始). 很多情况下 ...
- java基础24 线程、多线程及线程的生命周期(Thread)
1.1.进程 正在执行的程序称作为一个进程.进程负责了内存空间的划分 疑问1:windows电脑称之为多任务的操作系统,那么Windows是同时运行多个应用程序呢? 从宏观的角度:windows确实在 ...
随机推荐
- iOS Runtime(一)、objc_class深深的误解
现在网上讲解的objc_class 绝大部分是错的.18年.19年依然很多童鞋写着错误的Runtime文章发到网上,面试的时候基本绝大部分人都说着网上所谓的"正确答案". 一.错误 ...
- UVA 277 Puzzle
题意:输入5x5的字符串,输入操作,要求输出完成操作后的字符串. 注意:①输入的操作执行可能会越界,如果越界则按题目要求输出不能完成的语句. ②除了最后一次的输出外,其他输出均要在后面空一行. ③操作 ...
- BZOJ.4572.[SCOI2016]围棋(轮廓线DP)
BZOJ 洛谷 \(Description\) 给定\(n,m,c\).\(Q\)次询问,每次询问给定\(2*c\)的模板串,求它在多少个\(n*m\)的棋盘中出现过.棋盘的每个格子有三种状态. \( ...
- 狄克斯特拉算法(Python实现)
概述 狄克斯特拉算法--用于在加权图中找到最短路径 ps: 广度优先搜索--用于解决非加权图的最短路径问题 存在负权边时--贝尔曼-福德算法 下面是来自维基百科的权威解释. 戴克斯特拉算法(英语:Di ...
- npm install报错Unhandled rejection RangeError: Maximum call stack size exceededill install
故障 在使用npm install下载依赖的时候报错Unhandled rejection RangeError: Maximum call stack size exceededill instal ...
- vim技巧3
yyp复制当前行到下一行ddp剪切当前行到下一行cw:删除当前单词并进入插入模式xp:交换当前字符和右边字符s:删除光标所在的字符并进入插入模式I:在行首开始输入文字并进入插入模式A:在行尾开始输入文 ...
- JS中原始类型Null和Undefined
Undefined类型只有一个值,即undefined.当声明的变量还未被初始化时,变量的默认值为undefined.Null类型也只有一个值,即null.null用来表示尚未存在的对象,常用来表示函 ...
- xml 初步学习 读取
引入xml文件 function loadXMLDoc(dname) { if (window.XMLHttpRequest) { xhttp = new ...
- PAT Basic 1001
1001 害死人不偿命的(3n+1)猜想 (15 分) 卡拉兹(Callatz)猜想: 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把 (3n+1) 砍掉一半.这样一直反复 ...
- UIButton高亮状态卡顿
童鞋们有么有遇到过一个tableview或者是scrollview上放置一个button然后点击button,但是button的高亮状态切换不过来呢? 解决方案: 新建一个类继承自UITableVie ...