这篇文章主要是个人的学习笔记,是以例子来驱动的,加深自己对多线程的理解。


一:实现多线程的两种方法

1.继承Thread

 class MyThread1 extends Thread{
public void run(){
System.out.println("这是自定义的线程");
}
}

通过继承Thread,然后重写Thread中的run方法,把自己要实现的方法写在run()中

  class ThreadTest1{
public static void main(String[] args){
MyThread1 mythread = new MyThread1();
mythread.start();
}
}

2.实现Runnable接口

  class MyThread implements Runnable{
public void run(){
System.out.println("这是自定义的实现Runnable接口的线程");
}
}

实现Runnable接口,然后实现它的方法run

 class ThreadTest1{
public static void main(String[] args){
MyThread mythread = new MyThread();
Thread thread = new Thread(mythread);
thread.start();
}
}

把mythread传到Thread的构造方法中,然后就生成了一个线程。

二:线程的安全性问题

  class MyThread implements Runnable{
int i = 100;
public void run(){
while(true){
System.out.print(Thread.currentThread().getName()+i+“ ”);
Thread.yield();
i--;
if(i<0){
break;
}
}
}
}
 class ThreadTest{
public static void main(String[] args){
MyThread mythread = new MyThread();
Thread thread = new Thread(mythread);
Thread thread2 = new Thread(mythread);
thread.setName("线程A");
thread2.setName("线程B");
thread.start();
thread2.start();
}
}

ThreadTest的main运行结果:

线程A10 线程B10 线程A9 线程B8 线程A7 线程B6 线程A5 线程B4 线程A3 线程B2 线程B1 线程A0

这结果是不是很奇怪,为什么有线程A10 线程B10 。要是这是一个火车售票系统,那么不是卖个两个人同一个火车票了么?

也许这个例子过于简单,看不出什么,可以参考:http://www.blogjava.net/tscfengkui/archive/2010/11/10/337709.html?opt=admin

原因主要是线程A运行run方法,运行到System.out.println(),但是还没有运行到i--,可是这是线程B抢占到了资源,那么线程B开始运行,然后线程B又运行到了System.out.println(),然后线程A或者B中有一个运行i--.然后A再运行println()。

解决办法就是在线程运行run使用资源的时候交给他一把锁,等它把事情做完后在把锁给另一个要用这个资源的线程。这样就不会出现上述情况。 实现这个锁的功能就需要用到synchronized这个关键字。

synchronized这个关键字有两种用法1、放方法名前形成同步方法;2、放在块前构成同步块。

方法1:在方法名前形成同步方法

 class MyThread implements Runnable{
int i = 10;
public void run(){
/* for(int i = 0; i <100; i++){
//获得当前正在运行线程的名字
System.out.println(Thread.currentThread().getName()+i);
} */
this.meA();
}
public synchronized void meA(){
while(true){
System.out.print(Thread.currentThread().getName()+i+" ");
Thread.yield();
i--;
if(i<=0){
break;
}
}
}
}

运行结果

线程A10 线程A9 线程A8 线程A7 线程A6 线程A5 线程A4 线程A3 线程A2 线程A1 线程B0

方法二:放在块前构成同步块

比如上面例子中,只要在while中加入一个方法块

  while(true){
synchronized(this){
System.out.print(Thread.currentThread().getName()+i+" ");
Thread.yield();
i--;
if(i<0){
break;
}
}
}

那么实现的结果和上面是一样的。


这是我今天学习多线程的结果,多线程很深奥,越学越觉得好多还不懂,只能每天进步一点。

java 多线程学习笔记的更多相关文章

  1. java多线程学习笔记——详细

    一.线程类  1.新建状态(New):新创建了一个线程对象.        2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...

  2. JAVA多线程学习笔记(1)

    JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...

  3. Java多线程学习笔记(一)——多线程实现和安全问题

    1. 线程.进程.多线程: 进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天. 2.线程的特点: 1.运行任 ...

  4. Java多线程学习笔记

    进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...

  5. Java多线程学习笔记--生产消费者模式

    实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前 ...

  6. Java 多线程学习笔记:生产者消费者问题

    前言:最近在学习Java多线程,看到ImportNew网上有网友翻译的一篇文章<阻塞队列实现生产者消费者模式>.在文中,使用的是Java的concurrent包中的阻塞队列来实现.在看完后 ...

  7. java多线程学习笔记(三)

    java多线程下的对象及变量的并发访问 上一节讲到,并发访问的时候,因为是多线程,变量如果不加锁的话,会出现“脏读”的现象,这个时候需要“临界区”的出现去解决多线程的安全的并发访问.(这个“脏读”的现 ...

  8. Java多线程学习笔记(一)

    一 概述 一个进程只有一个至少会运行一个线程,Java中同样存在这样,在调用main方法的时候,线程又JVM所创建. package link.summer7c.test; public class ...

  9. java多线程学习笔记(四)

    上一节讲到Synchronized关键字,synchronized上锁的区域:对象锁=方法锁/类锁 本节补充介绍一下synchronized锁重入: 关键字synchronized拥有锁重入的功能,也 ...

随机推荐

  1. 推荐两个Laravel插件网站

    1.https://packagist.org 2.http://packalyst.com

  2. Http Analyzer 数据抓包

    一.工具简介 这是一款实时分析 HTTP/HTTPS 数据流的工具.它可以实时捕捉HTTP/HTTPS 协议数据,可以显示许多信息(包括:文件头.内容.Cookie.查询字符窜.提交的数据.重定向的U ...

  3. MySQL----基本数据类型

    1.数值型: tinyint:1字节 smallint:2字节 mediumint:3字节 int:4字节 bigint:8字节 float:4字节 double:8字节 decimal(m,c):m ...

  4. sudo apt-get update

    要用apt-get这种方式安装LAMP时,最好先运行下面在命令升级自己的系统这样是为了更新源,而如果你找的源不好,可能安装LMAP失败.#sudo apt-get update 获得最近的软件包的列表 ...

  5. ODI 系列学习--整体架构概念

    ODI 系列学习--整体架构概念 ODI整体架构没有Oracle Database复杂,因为它属于程序功能的使用,更多是程序开发和配置的工作,当然ODI的优化涉及到很多数据库优化的工作,从整体架构入手 ...

  6. Keil MDK下如何设置非零初始化变量

    一些工控产品,当系统复位后(非上电复位),可能要求保持住复位前RAM中的数据,用来快速恢复现场,或者不至于因瞬间复位而重启现场设备.而keil mdk在默认情况下,任何形式的复位都会将RAM区的非初始 ...

  7. Qt for Android遇到的几个错误解决[Win7 + Qt5.6 +jdk 8u91]

    [1]SDK Manager无法更新Android SDK安装后需要运行SDK Manager下载安装包,默认从google网站下载,但被GWF和谐了,感谢一位网友提供的镜像站点.具体步骤是:运行SD ...

  8. mysql允许远程IP访问

    默认情况下Linux内的mysql数据库mysql,user表内的用户权限只是对localhost即本机才能登陆.需要更改权限: mysql> Grant all privileges on * ...

  9. 如果在文档已完成加载后执行 document.write,整个 HTML 页面将被覆盖

    <!DOCTYPE html> <html> <body> <h1>My First Web Page</h1> <p>My F ...

  10. linux内核源码阅读之facebook硬盘加速flashcache之六

    其实到目前为止,如果对读流程已经能轻松地看懂了,那么写流程不需要太多脑细胞.我觉得再写下去没有太大的必要了,后面想想为了保持flashcache完整性,还是写出来吧.接着到写流程: 1530stati ...