java多线程编程核心技术----心得1

1.线程和进程

进程和线程的例子很多,因为是学习笔记,那就说一种我自己感觉很好理解的,就是我们天天使用的QQ,但我们运行QQ.exe程序时,进程就开始,我们可以同时打开对个聊天窗口,可以多人视频过,甚至可以一边视频一边手动聊天(可能音响坏了吧 。。。),其中每一个任务完全可以理解成是“线程”在工作,传音乐,图片表情,传文件等功能都有对应的线程在后台默默运行。

2使用多线程

2.1.1  一个类怎么就能变成“线程”了呢?

在回答上面的问题之前;我们首先要认识一个类和一个借口,Thread类和Runnable借口。实现多线程编程的方法有两种

1)继承Thread类(java的特点就是单继承,如果一个类既要继承别的类,还想实现线程,那么用Thread类肯定做不到)

2)实现Runnable借口(支持“多继承”就靠Runnable借口了,一边实现一边继承,但不过是那种方法创建的线程工作的性质是一样的)

继承Thread类

让我们先来看看源码Thread类的结构(其实Thread类也是实现的Runnable借口)

public  class Thread implements Runnable

下面用一段简单的代码实现一个使用继承Thread类的线程

package test;

public class ThreadDemo01 {
public static void main(String[] args) {

TestThread tt=new TestThread();//创建线程对象
tt.start();//激活一个线程
for(int i=0;i<5;i++){
System.out.println("main线程正在运行");
try {
Thread.sleep(2000);//睡眠2s
} catch (Exception e) {
// TODO: handle exception
}
}

}

}

class TestThread extends Thread{

public void run(){//重写父类run方法
for(int i=0;i<5;i++){
System.out.println("TestThread正在运行");
try {
Thread.sleep(1000);//睡眠1秒
} catch (Exception ex) {
// TODO: handle exception
ex.printStackTrace();
}

}

}

}

从上面的代码需要注意的是:1)进程Thread类的类必须从写run方法  。2)激活一个线程使用的是Start方法(实际是改变了线程的状态)

3)如果你多运行两遍这个程序你会发现结果不一样,这体现了多线程执行顺序是不确定的(主要看CPU时间片的长短)

实现Runnable借口

直接上代码

package test;

public class ThreadDemo02 {
public static void main(String[] args) {
TestThread tt=new TestThread();
new Thread(tt).start();//激活一个线程
for(int i=0;i<5;i++){
System.out.println("main正在运行");
try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
}
}

}
class TestThread02 implements Runnable {

@Override
public void run() {
for(int i=0;i<5;i++){
System.out.println("TestThread正在运行");
try {
Thread.sleep(1000);

} catch (Exception e) {
// TODO: handle exception
}
}

}

}

实现Runnable借口需要注意:1)我虽然实现了Runnable借口,但用的仍然是Thread类的Start方法激活线程(原因在于查看jdk文档得知Runnable只有一个run方法没有其他方法)2)Thread类的构造函数 public Thread(Runnable  target)可以将借口的实现类对象作为参数,实例化出一个Thread类的对象

实例变量和线程安全

自定义线程类中的实例变量针对其他线程可以有共享和不共享之分。这也是多线程交互时很重要的知识点。

这里举一个买票的例子,火车票有很多的代受点,现在要求四个代受点共要卖出去5张票,

方案1 使用继承Thread类的方法

package test;

public class ThreadDemo03 {
public static void main(String[] args) {
TestThread03 t=new TestThread03();

//一个线程对象对象只能启动一个线程
t.start();
t.start();
t.start();
t.start();
}

}
class TestThread03 extends Thread{
private int i=5;
public void run(){
while(i>0){
System.out.println(Thread.currentThread().getName()+"出售票"+i);
i-=1;
}
}
}

执行一下会发现报了异常java.lang.IllegalThreadStateException这就说明这种写法不能起到“票源共享”,也说明一个对象只能启动一个线程

再来看方案2

package test;

public class ThreadDemo03 {
public static void main(String[] args) {
//TestThread03 t=new TestThread03();
new TestThread03().start();
new TestThread03().start();
new TestThread03().start();
new TestThread03().start();
}

}
class TestThread03 extends Thread{
private int i=5;
public void run(){
while(i>0){
System.out.println(Thread.currentThread().getName()+"出售票"+i);
i-=1;
}
}
}

从执行结果看是四个线程了,但票数不对了,这样看来是每个线程5张票,和我们的初衷4个线程共卖5张票严重不符,那么我们再来做一个小小的改动,将变量i设置成静态变量

方案3

package test;

public class ThreadDemo03 {
public static void main(String[] args) {
//TestThread03 t=new TestThread03();
new TestThread03().start();
new TestThread03().start();
new TestThread03().start();
new TestThread03().start();
}

}
class TestThread03 extends Thread{
private static int i=5;
public void run(){
while(i>0){
System.out.println(Thread.currentThread().getName()+"出售票"+i);
i-=1;
}
}
}

从执行的结果看出似乎完成了资源共享的要求,但是我们发现有的票出现了“一票多卖”的现象,这就非线程安全问题,这个稍后解决,先来看看使用Runnable借口怎么完成资源共享

运行如下代码

方案4

package test;

public class ThreadDemo03 {
public static void main(String[] args) {
TestThread03 t=new TestThread03();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}

}
class TestThread03 implements Runnable{
private int i=5;
public void run(){
while(i>0){
System.out.println(Thread.currentThread().getName()+"出售票"+i);
i-=1;
}
}
}

从方案4和方案3对比来看 使用Runnable借口似乎比使用Thread类有优势

现在讨论一下非线程安全问题

前面的方案3和方案4解决了资源共享问题,但出现了多个线程共卖一张票的问题(原因:假设票数现在是5,线程1看见了,执行了run方法,本应票数减1但是这时线程1的CPU时间片到了,必须退出,换别的线程,这时线程2看见的仍然是i=5的票数,于是它有卖了一遍)

要想解决这个问题实现一票一买必须要引用关键字synchronized(使。。。同步)

同不代码块的语法格式:

synchronized(对象){

需要同步的代码

}

还是先执行代码

package test;

public class ThreadDemo04 {

public static void main(String[] args) {
TestThread04 t=new TestThread04();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}

}
class TestThread04 implements Runnable{
private int i =5;
@Override
public void run() {
while(true){
synchronized (this) {
if(i<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"出售票"+i);
i-=1;
}
}

}

}

使用synchronized代码块的目的就是保证其中内容的原子性(要么不执行,要执行就一定执行完,不存在执行一半中断的情况)

且同一时刻进入临界区(synchronized代码块的)只能有一个线程

不光能使用代码块可也是用synchronized修饰的方法来解决“非线程安全问题”

执行如下代码:

package test;

public class ThreadDemo06 {
public static void main(String[] args) {
TestThread06 t=new TestThread06();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
new Thread(t).start();
}

}
class TestThread06 implements Runnable{
private int i=5;
@Override
public void run() {

while(i>0){
sale();
}

}
public synchronized void sale(){
if(i>0)
System.out.println(Thread.currentThread().getName()+"出售票"+i);

try {
Thread.sleep(1000);
} catch (Exception e) {
// TODO: handle exception
}
i-=1;
}

}

待续。。媳妇让我睡觉

时间: 2024-11-03 22:19:12

java多线程编程核心技术----心得1的相关文章

《Java多线程编程核心技术》推荐

写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点Java基础,你就可以尝试去阅读它,相信定会收获甚大! 博主之前网上找了很久都没完整pdf电子版的,只有不全的试读版,这里博主提供免费.清晰.完整版供各位猿友下载: http://download.csdn.net/detail/u013142781/9452683 刚刚已经提到,<Java多线程编程核

JAVA读书推荐----《深入分析Java Web技术内幕》--《java多线程编程核心技术》--《大型网站技术架构 核心原理与案例分析》-《Effective Java中文版》

(1)  首先推荐的不是一本书,而是一个博客,也是我们博客园另外一位博友java_my_life. 目前市面上讲解设计模式的书很多,虽然我前面讲了看书是最好的,但是对设计模式感兴趣的朋友们,我推荐的是这个博客.这位博友的设计模式讲得非常非常好,我认为90%的内容都是没有问题且很值得学习的,其讲解设计模式的大体路线是: 1.随便开篇点明该设计模式的定义 2.图文并茂讲解该设计模式中的结构 3.以详细的代码形式写一下该种设计模式的实现 4.补充内容 5.讲解该设计模式的优缺点 对于一个设计模式我们关

《Java 多线程编程核心技术》- 笔记

作为业务开发人员,能够在工作中用到的技术其实不多.虽然平时老是说什么,多线程,并发,注入,攻击!但是在实际工作中,这些东西不见得用得上.因为,我们用的框架已经把这些事做掉了. 比如web开发,外面有大量的请求进来,按理说,我们应该考虑并发问题.但其实,spring接到请求,分配到controller之后,就已经是线程安全的了,所以我们要做的就是,从controller开始,到最后请求响应结束,保证线程安全即可. 多线程好像有很多东西需要注意,阅读<Java 多线程编程核心技术>后,做个总结,总

Java多线程编程核心技术(三)多线程通信

线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时还会使程序员对各线程任务在处理的过程中进行有效的把控与监督.在本章中需要着重掌握的技术点如下: 使用wait/notify实现线程间的通信 生产者/消费者模式的实现 方法join的使用 ThreadLocal类的使用 1.等待 / 通知机制 通过本节可以学习到,线程与线程之间不是独立的个体,它们彼此

《java多线程编程核心技术》

第一章 java多线程技能 1.1 进程和多线程的概念及线程的优点 1.2 使用多线程 1.2.1 继承thread类 1.2.2实现runnable接口 1.2.3 实例变量与线程安全 1.2.4 留意i--与system.out.println()的异常 1.3 currentthread()方法 1.4 isalive()方法 1.5 sleep()方法 1.6 getid()方法 1.7 停止线程 1.7.1 停止不了的线程 1.7.2 判断线程是否是停止状态 1.7.3 能停止的进程-

一、java多线程编程核心技术之(笔记)——多线程的实现

概念:可以理解为在进程中独立运行的子任务.比如,QQ.exe在运行时就有很多子任务在运行,好友视屏线程,下载文件线程,传输数据线程等等. 优点:1.提升CPU资源利用率,提升系统性能. 一.多线程的实现 1.1.继承Thread类(extends Thread),Thread类实现了Runnable接口 public class Thread implements Runnable public class MyThread extends Thread{ @Override public vo

Java多线程编程核心技术(一)

先提一下进程,可以理解为操作系统管理的基本单元. 而线程呢,在进程中独立运行的子任务.举个栗子:QQ.exe运行时有很多子任务在同时运行,比如好友视频线程.下载视频线程.传输数据线程等等. 多线程的优势?    在单任务运行环境中,需要排队执行,也就是我们所说的同步,CPU利用率大幅降低.    多任务运行环境中,CPU可以来回切换,系统运行效率提升.多线程是异步的,所以千万不要把 Eclipse IDEA里的代码顺序当成线程执行顺序. 实现? 继承Thread类 package chapter

Java多线程编程核心技术读书笔记(3)-线程通信

线程是操作系统中独立的个体,但是这些个体如果无法经过特殊的处理就不能成为一个整体.线程间通信可以实现线程间的信息互换.相互唤起等功能,是系统的交互性更加强大,大大提高CPU的利用率,同时还能让开发者对各个线程任务有清晰的把控和监督,最常用的线程通信方法就是--等待/通知机制. 一.等待/通知机制 1.wait() / notify() 等待/通知机制在生活中比比皆是,例如:厨师/服务员的菜品传递台.生产者/消费者模式,JDK中通过Object里面的两个方法 wait() / notify() 来

Java多线程编程核心技术

1,Java并发--详解this与Thread.currentThread()的区别:https://blog.csdn.net/championhengyi/article/details/76664491 Thread.currnetThread()是指当前运行的线程,在比如在构造函数的时候是主线程 this表示当前对象的引用,有Thread1 ,Thread thread2 = new Thread(Thread1),this现在指的是thread1的引用,而且不活那种 原文地址:http