java多线程基础_java线程基础
1. 创建线程的两种方式
2. 线程的生命周期
3. 同步的方式
4. 死锁
5. 生产消费模型、监控模型
创建线程的两种方式
Java代码
publicclassThread1extendsThread {
privateintj;
// 重写run方法
publicvoidrun() {
for(; j <100; j++) {
System.out.println(getName() +" "+ j);
}
}
// 主函数
publicstaticvoidmain(String args[]) {
for(inti =0; i <100; i++) {
// 打印主线程执行信息
System.out.println(Thread.currentThread().getName() +" "+ i);
if(i ==20) {
// 新启两个线程
newThread1().start();
newThread1().start();
}
}
}
}
publicclassThread2implementsRunnable {
privateintj;
// 实现run方法
publicvoidrun() {
for(; j <100; j++) {
System.out.println(Thread.currentThread().getName() +" "+ j);
}
}
// 主方法
publicstaticvoidmain(String args[]) {
for(inti =0; i <100; i++) {
// 打印主线程执行信息
System.out.println(Thread.currentThread().getName() +" "+ i);
if(i ==20) {
// 新启两个线程
Thread2 thread=newThread2();
newThread(thread,"新线程1").start();
newThread(thread,"新线程2").start();
}
}
}
}
public class Thread1 extends Thread {
private int j;
// 重写run方法
public void run() {
for (; j < 100; j++) {
System.out.println(getName() + " " + j);
}
}
// 主函数
public static void main(String args[]) {
for (int i = 0; i < 100; i++) {
// 打印主线程执行信息
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
// 新启两个线程
new Thread1().start();
new Thread1().start();
}
}
}
}
public class Thread2 implements Runnable {
private int j;
// 实现run方法
public void run() {
for (; j < 100; j++) {
System.out.println(Thread.currentThread().getName() + " " + j);
}
}
// 主方法
public static void main(String args[]) {
for (int i = 0; i < 100; i++) {
// 打印主线程执行信息
System.out.println(Thread.currentThread().getName() + " " + i);
if (i == 20) {
// 新启两个线程
Thread2 thread=new Thread2();
new Thread(thread,"新线程1").start();
new Thread(thread,"新线程2").start();
}
}
}
}
结果:
从图片上我们可以看到,第一张图片数据之间没有实现共享,但是第二张图片,我们可以看到线程1和线程2共享了线程类的实例属性,这是因为程序所创建的Runnable对象只是线程的的target,而多个线程可以共享一个target;
对于用继承Thread和实现Runnable,采用Runnable的话该实现类还可以进行继承,扩展性更强;
启动一个线程用的是start(),而不是run();如果直接用run()则会将它当作一个普通的方法来使用;用start(),则会将run方法当作线程执行体来处理;
前面的两个示例,实际上至少有三条线程,主线程和程序显示创建的两条线程;主线程的线程执行体不是由run方法来确定的,而是由main方法来确定的
线程的生命周期
当程序用new关键字创建一个线程之后,该线程就处于新建状态,此时它和其它Java对象一样,仅仅由Java虚拟机为其分配内存,并初始化了其成员变量的值。当线程调用了start方法后,该线程处于就绪状态;
同步的方式
一.synchronized关键字保证同步
锁定方法:表示这个方法同时只能被一个线程访问
Java代码
//同步方法 同步监视器为this
publicsynchronizedintgetM1(intcount){
return1;
}
//同步方法 同步监视器为this
public synchronized int getM1(int count){
return 1;
}
锁定对象:表示其限定的代码块只能同时被一个线程访问
Java代码
//同步代码块
publicvoidgetM2(){
synchronized(obj){
//代码块,obj为同步监视器
}
}
//同步代码块
public void getM2(){
synchronized(obj){
//代码块,obj为同步监视器
}
}
二.新用JDK1.5新的同步机制
Java代码
privateLock lock=newReentrantLock();
//在方法内使用同步锁
publicvoidgetM3(){
//开始锁
lock.lock();
//同步区。。。
try{
}finally{
//释放锁
lock.unlock();
}
}
private Lock lock=new ReentrantLock();
//在方法内使用同步锁
public void getM3(){
//开始锁
lock.lock();
//同步区。。。
try{
}finally{
//释放锁
lock.unlock();
}
}
死锁
当两线程相互等待对方释放同步监视器时就会出现死锁,一旦出现死锁,整个程序既不会发生任何的异常,也不会给出任何的提示,只是所有线程处理阻塞状态,无法继续
Java代码
classA {
synchronizedvoidfoo(B b) {
String name = Thread.currentThread().getName();
System.out.println(name +" entered A.foo");
try{
Thread.sleep(1000);
}catch(Exception e) {
System.out.println("A Interrupted");
}
System.out.println(name +" trying to call B.last()");
// 因为b对象被锁住了,调用b内的方法时,在等锁的释放
b.last();
}
synchronizedvoidlast() {
System.out.println("Inside A.last");
}
}
classB {
synchronizedvoidbar(A a) {
String name = Thread.currentThread().getName();
System.out.println(name +" entered B.bar");
try{
Thread.sleep(1000);
}catch(Exception e) {
System.out.println("B Interrupted");
}
System.out.println(name +" trying to call A.last()");
// 因为a对象被锁住了,调用a内的方法时,在等锁的释放
a.last();
}
synchronizedvoidlast() {
System.out.println("Inside A.last");
}
}
classDeadlockimplementsRunnable {
A a =newA();
B b =newB();
Deadlock() {
Thread.currentThread().setName("MainThread");
Thread t =newThread(this,"RacingThread");
t.start();
a.foo(b);// 同步监视器为a
System.out.println("Back in main thread");
}
publicvoidrun() {
b.bar(a);// 同步监视器为b
System.out.println("Back in other thread");
}
publicstaticvoidmain(String args[]) {
newDeadlock();
}
}
class A {
synchronized void foo(B b) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered A.foo");
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("A Interrupted");
}
System.out.println(name + " trying to call B.last()");
// 因为b对象被锁住了,调用b内的方法时,在等锁的释放
b.last();
}
synchronized void last() {
System.out.println("Inside A.last");
}
}
class B {
synchronized void bar(A a) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered B.bar");
try {
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("B Interrupted");
}
System.out.println(name + " trying to call A.last()");
// 因为a对象被锁住了,调用a内的方法时,在等锁的释放
a.last();
}
synchronized void last() {
System.out.println("Inside A.last");
}
}
class Deadlock implements Runnable {
A a = new A();
B b = new B();
Deadlock() {
Thread.currentThread().setName("MainThread");
Thread t = new Thread(this, "RacingThread");
t.start();
a.foo(b); // 同步监视器为a
System.out.println("Back in main thread");
}
public void run() {
b.bar(a); // 同步监视器为b
System.out.println("Back in other thread");
}
public static void main(String args[]) {
new Deadlock();
}
}
生产消费模型、监控模型
Java代码
//生产消费模型
publicclassMain {
publicstaticvoidmain(String args[]) {
List list =newArrayList();
newProduct(list).start();
newCustomer(list).start();
}
}publicclassEgg {
privateintid;
privateString name;
publicintgetId() {
returnid;
}
publicvoidsetId(intid) {
this.id = id;
}
publicString getName() {
returnname;
}
publicvoidsetName(String name) {
this.name = name;
}
publicString toString() {
returnid +" "+ name;
}
}publicclassProductextendsThread {
privateList list;
privateintcount;
publicProduct(List list) {
this.list = list;
}
// 重写run方法
publicvoidrun() {
System.out.println("生产线程启动");
while(true) {
try{
Thread.sleep(100);
synchronized(list) {
//还有鸡蛋时
while(list.size() >0) {
list.wait();
}
//没有鸡蛋时
while(list.size()==0){
Egg egg=newEgg();
egg.setId(count++);
egg.setName("鸡蛋");
System.out.println("生产线程生产"+egg.toString());
list.add(egg);
//通知消费线程
list.notify();
}
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}publicclassCustomerextendsThread {
privateList list;
publicCustomer(List list) {
this.list = list;
}
// 重写run方法
publicvoidrun() {
System.out.println("消费线程启动");
while(true) {
try{
Thread.sleep(100);
synchronized(list) {
//没有则等待
while(list.size() ==0) {
list.wait();
}
//有鸡蛋时
while(list.size()>0){
System.out.println("消费线程消费"+list.remove(0).toString());
//通知生产线程
list.notify();
}
}
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
//生产消费模型
public class Main {
public static void main(String args[]) {
List list = new ArrayList();
new Product(list).start();
new Customer(list).start();
}
}public class Egg {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return id + " " + name;
}
}public class Product extends Thread {
private List list;
private int count;
public Product(List list) {
this.list = list;
}
// 重写run方法
public void run() {
System.out.println("生产线程启动");
while (true) {
try {
Thread.sleep(100);
synchronized (list) {
//还有鸡蛋时
while (list.size() > 0) {
list.wait();
}
//没有鸡蛋时
while(list.size()==0){
Egg egg=new Egg();
egg.setId(count++);
egg.setName("鸡蛋");
System.out.println("生产线程生产"+egg.toString());
list.add(egg);
//通知消费线程
list.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}public class Customer extends Thread {
private List list;
public Customer(List list) {
this.list = list;
}
// 重写run方法
public void run() {
System.out.println("消费线程启动");
while (true) {
try {
Thread.sleep(100);
synchronized (list) {
//没有则等待
while (list.size() == 0) {
list.wait();
}
//有鸡蛋时
while(list.size()>0){
System.out.println("消费线程消费"+list.remove(0).toString());
//通知生产线程
list.notify();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Java代码
//监控模型public class Control implements Runnable {
// 存放统计线程的队列
privatestaticList list =newArrayList();
// 主函数
publicstaticvoidmain(String args[]) {
// 取得系统的根目录个数
java.io.File[] dirF = java.io.File.listRoots();
// 根据目录创建统计纯种个数
for(inti =0; i
CountFile cf =newCountFile(dirF[i].getAbsolutePath());
cf.start();
list.add(cf);
}
System.out.println(dirF.length +" 个统计线程已启动");
// 启动监视线程
newThread(newControl()).start();
System.out.println("监视线程已启动");
}
// 实现run方法
publicvoidrun() {
booleanflag =true;
String result ="";
while(flag) {
for(inti =0; i
if(list.get(i).isFinished()) {
// 取得统计结果
result += list.get(i).getResult();
// 移出统计完的线程
list.remove(i);
}
}
// 全部统计完
if(list.isEmpty()) {
flag =false;
}
try{
Thread.sleep(1000);
}catch(Exception e) {
e.printStackTrace();
}
}
System.out.println("统计结果如下:");
System.out.println(result);
}
}publicclassCountFileextendsThread {
privateString root;// 进行搜索的根目录的名字
privateintlengthCount;// 所有文件长度
privateintdirCount;// 目录数
privateintrealFileCount;// 统计的真正文件数量
privatebooleanfinished =false;
// 构造时传入搜索根目录名
publicCountFile(String root) {
this.root = root;
}
/**
* 查看线程是否统计结束
*
* @return
*/
publicbooleanisFinished() {
returnfinished;
}
/**
* 返回统计结果
*
* @return
*/
publicString getResult() {
StringBuffer result =newStringBuffer();
result.append(root +"盘统计结果如下:\r\n");
result.append(" 文件数量: "+ realFileCount);
result.append(" 目录数: "+ dirCount);
result.append(" 文件总长度(单位K): "+ lengthCount /1204);
result.append("\r\n");
returnresult.toString();
}
// 重写run方法
publicvoidrun() {
longstart = System.currentTimeMillis();
lengthCount = countProcess(root);
longcost = System.currentTimeMillis() - start;
finished =true;
}
/**
* 统计目录下文件的长度
*
* @param root
* 要统计的目录
* @return 目录下文件的长度
*/
privateintcountProcess(String root) {
intcount =0;
File dirFile =newFile(root);
// 目录不存在
if(!dirFile.exists()) {
returncount;
}
// 获得目录下的所有文件组成的数组
File[] subFile = dirFile.listFiles();
if(subFile ==null) {
returncount;
}
// 对这个数组进行遍历
for(inti =0; i
// 是个目录
if(subFile[i].isDirectory()) {
dirCount++;
count += countProcess(subFile[i].getAbsolutePath());// 用递归计算该目录下的文件长度
}
// 是一个文件
if(subFile[i].isFile()) {
realFileCount++;
count += subFile[i].length();
}
}
returncount;
}
}
//监控模型public class Control implements Runnable {
// 存放统计线程的队列
private static List list = new ArrayList();
// 主函数
public static void main(String args[]) {
// 取得系统的根目录个数
java.io.File[] dirF = java.io.File.listRoots();
// 根据目录创建统计纯种个数
for (int i = 0; i < dirF.length; i++) {
CountFile cf = new CountFile(dirF[i].getAbsolutePath());
cf.start();
list.add(cf);
}
System.out.println(dirF.length + " 个统计线程已启动");
// 启动监视线程
new Thread(new Control()).start();
System.out.println("监视线程已启动");
}
// 实现run方法
public void run() {
boolean flag = true;
String result = "";
while (flag) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).isFinished()) {
// 取得统计结果
result += list.get(i).getResult();
// 移出统计完的线程
list.remove(i);
}
}
// 全部统计完
if (list.isEmpty()) {
flag = false;
}
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("统计结果如下:");
System.out.println(result);
}
}public class CountFile extends Thread {
private String root;// 进行搜索的根目录的名字
private int lengthCount;// 所有文件长度
private int dirCount;// 目录数
private int realFileCount;// 统计的真正文件数量
private boolean finished = false;
// 构造时传入搜索根目录名
public CountFile(String root) {
this.root = root;
}
/**
* 查看线程是否统计结束
*
* @return
*/
public boolean isFinished() {
return finished;
}
/**
* 返回统计结果
*
* @return
*/
public String getResult() {
StringBuffer result = new StringBuffer();
result.append(root + "盘统计结果如下:\r\n");
result.append(" 文件数量: " + realFileCount);
result.append(" 目录数: " + dirCount);
result.append(" 文件总长度(单位K): " + lengthCount / 1204);
result.append("\r\n");
return result.toString();
}
// 重写run方法
public void run() {
long start = System.currentTimeMillis();
lengthCount = countProcess(root);
long cost = System.currentTimeMillis() - start;
finished = true;
}
/**
* 统计目录下文件的长度
*
* @param root
* 要统计的目录
* @return 目录下文件的长度
*/
private int countProcess(String root) {
int count = 0;
File dirFile = new File(root);
// 目录不存在
if (!dirFile.exists()) {
return count;
}
// 获得目录下的所有文件组成的数组
File[] subFile = dirFile.listFiles();
if (subFile == null) {
return count;
}
// 对这个数组进行遍历
for (int i = 0; i < subFile.length; i++) {
// 是个目录
if (subFile[i].isDirectory()) {
dirCount++;
count += countProcess(subFile[i].getAbsolutePath());// 用递归计算该目录下的文件长度
}
// 是一个文件
if (subFile[i].isFile()) {
realFileCount++;
count += subFile[i].length();
}
}
return count;
}
}
java多线程基础_java线程基础相关推荐
- java多线程构造函数_java线程基础巩固---多线程与JVM内存结构的关系及Thread构造函数StackSize的理解...
多线程与JVM内存结构的关系[了解]: 对于最后一个有疑问的构造中stackSize参数,其实学过编程滴人从参数字面就比较容易理解,栈大小嘛,这里从官方文档上来了解一下这个参数: 而之前在学习java ...
- java多线程抽奖_java 线程池、多线程并发实战(生产者消费者模型 1 vs 10) 附案例源码...
导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...
- java多线程示例_Java线程示例
java多线程示例 Welcome to the Java Thread Example. Process and Thread are two basic units of execution. C ...
- java+向前进一_Java 线程基础
前言 线程并发系列文章: 熟练掌握线程原理与使用是程序员进阶的必经之路,网上很多关于Java线程的知识,比如多线程之间变量的可见性.操作的原子性,进而扩展出的Volatile.锁(CAS/Synchr ...
- java多线程 门闩_Java线程与并发编程实践----同步器(倒计时门闩,同步屏障)...
Java提供的synchronized关键字对临界区进行线程同步访问.由于基于synchronized很难 正确编写同步代码,并发工具类提供了高级的同步器.倒计时门闩(countdown latch) ...
- java线程抢占式执行,Java并发基础(一)-线程基础
原标题:Java并发基础(一)-线程基础 只要涉及到线程,其运行结果就是不确定的,虽然说java很早就提供了线程以及并发的支持,但是我们需要知道,线程是完全交给调度器的.有很多同学在编写书上的代码时, ...
- Java多线程系列--“JUC线程池”06之 Callable和Future
转载自 Java多线程系列--"JUC线程池"06之 Callable和Future Callable 和 Future 简介 Callable 和 Future 是比较有趣的一 ...
- Java多线程之守护线程实战
转载自 Java多线程之<<守护线程>>实战 定义 什么是守护线程?与守护线程相对应的就是用户线程,守护线程就是守护用户线程,当用户线程全部执行完结束之后,守护线程才会跟着结束 ...
- java多线程面试_Java多线程和并发基础面试问答,看过后你不会后悔
***:Java多线程面试问题 1:进程和线程之间有什么不同? 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java ...
最新文章
- python 图表_python导出excel charts图表
- Servlet(3):Cookie
- 基于Quartus II软件FPGA与PC之间的串行通信系统开发(9000+字)
- 30 天精通 RxJS (01):认识 RxJS
- java中s方法_Java中Arrys数组常用的方法
- SAP RFC 获取BDC 消息文本的实现
- 作者:袁书寒,男,同济大学博士生。
- fastreport dll_报表如何连接到VistaDB嵌入式数据库?FastReport.Net轻松搞定
- api 原生hbase_数据查询的玄铁剑:云HBase原生二级索引发布
- 鸿蒙系统受谷歌影响吗,华为鸿蒙系统,会受到人们的欢迎吗?
- Spring 三种bean装配的方式
- w3school入门自学免费网站推荐
- PHP 中跳转网页的三种方法
- ElasticSearch - 嵌套对象 nested
- 房产纠纷官司费用是多少
- Varnish 安装部署
- linux ftp 服务配置
- 【笔记】分布式网络与分布式账本
- Excel - 图文详解Excel中相对引用和绝对引用的区别
- 使用动态规划求解算法问题的五大特点总结(附基于Python的参考代码)