1. 线程、进程、多线程:

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

2.线程的特点:

1.运行任何一个java程序,jvm在运行时都会创建一个main线程来执行main方法。

2.一个java应用程序至少有两个线程,一个是主线程,负责main方法的执行,一个是垃圾回收器线程,负责回收垃圾。

3.我们可以利用Thread.currentThread().getName()获得当前线程名字。

3.多线程的优点:

1.可以同时处理多个任务。

2.提高资源的利用率。

缺点:

1.增加了CPU负担,因为CPU要不断的来回切换。

2.降低了一个进程中线程的执行概率。

3.存在线程安全问题。

4.会发生死锁现象。

4.如何创建一个线程:

方式一:  1.自定义一个类继承Thread类;

      2.重写Thread类中的run方法(自定义线程的任务代码就放在run方法里);

3.创建Thread子类的对象,并且调用start方法开启线程。(run方法不能直接调用)

class Demo extends Thread{

    public void run(){    //重写run方法
for(int i=0;i<100;i++){
System.out.println("自定义线程"+i) } } public static void main(String[] args){ Demo d = new Demo();
d.start(); //调用start方法开启线程 for(int i=0;i<100;i++){
System.out.println("main线程"+i) }
} }

方式二:实现Runnable接口,Thread类中有构造方法,可以传递Runnable实例。

class Demo1 implements Runnable{

    public void run(){    //重写run方法
for(int i=0;i<100;i++){
System.out.println("自定义线程"+i) } } public static void main(String[] args){ Demo d = new Demo();
Thread thread = new Thread(d);
thread .start(); //调用start方法开启线程 for(int i=0;i<100;i++){
System.out.println("main线程"+i) }
} }

方式三:实现Callable接口

* Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。

* Callable和Runnable有几点不同:

* (1)Callable规定的方法是call(),而Runnable规定的方法是run().

* (2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。

* (3)call()方法可抛出异常,而run()方法是不能抛出异常的。

* (4)运行Callable任务可拿到一个Future对象,

* Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。

* 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。

实现代码:

package xiancheng.callable;

import java.util.concurrent.Callable;

public class MyCallable implements Callable<Integer>{

    @Override
public Integer call() throws Exception {
int sum = 0;
for(int i = 0;i<10;i++){
sum+=i;
}
return sum;
}
}
public class CallableTest {

    public static void main(String[] args) throws Exception{
/*// 第一种方式:通过线程池来获取线程
ExecutorService executor = Executors.newCachedThreadPool();//创建线程池
Future<Integer> future = executor.submit(new MyCallable());//ExecutorService中的submit方法接受一个Runnable或者Callable,然后返回一个Future来获得任务的执行结果或者取消任务。
System.out.println("result:" + future.get());
executor.shutdown();*/ //第二种方式
MyCallable mc = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<Integer>(mc);
Thread thread = new Thread(futureTask);
thread.start();
System.out.println("result:" + futureTask.get());
} }

结果为:result:45

Executors、ExecutorService介绍请移步Java多线程学习笔记(二)——Executor,Executors,ExecutorService比较

Future、FutureTask介绍请移步Java多线程学习笔记(三)——Future和FutureTask

5.实例变量与线程安全

场景一:数据不共享情况

public class MyThread extends Thread{
private int i = 5;
public MyThread(String s){
super();
this.setName(s);
} public void run(){
super.run();
while(i>0){
i--;
System.out.println("由"+Thread.currentThread().getName()+"计算i="+i);
}
}
}
public class Run {

    public static void main(String[] args) {
MyThread a = new MyThread("A");
MyThread b = new MyThread("B");
MyThread c = new MyThread("C");
a.start();
b.start();
c.start();
} }

运行结果:

我们创建三个独立的线程,每个线程有自己的变量。不会出现安全问题。

场景二:五个售票员卖票

public class MyThread extends Thread{
private int i = 5;
public void run(){
super.run();
i--;
System.out.println("由"+Thread.currentThread().getName()+"计算i="+i);
}
}
public class Run {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread a = new Thread(myThread,"A");
Thread b = new Thread(myThread,"B");
Thread c = new Thread(myThread,"C");
Thread d = new Thread(myThread,"D");
Thread e = new Thread(myThread,"E"); a.start();
b.start();
c.start();
d.start();
e.start();
}
}
 
运行结果:
 
线程A,C,B打印出相同的数字,说明产生了线程安全问题,我们想要的结果是递减的。
解决方法:
public class MyThread extends Thread{
private int i = 5;
synchronized public void run(){
super.run();
i--;
System.out.println("由"+Thread.currentThread().getName()+"计算i="+i);
}
}

运行结果:

由A计算i=4
由D计算i=3
由C计算i=2
由B计算i=1
由E计算i=0

 6.线程生命周期:

1.创建阶段:当创建线程的继承类时就实现这一阶段。new Demo();

2.可运行阶段:当调用start方法时。

3.运行状态:线程拿到CPU执行权时。当执行权被夺走时又会回到可运行阶段。

4.临时阻塞状态:是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入可运行阶段,才有机会转到运行状态。

临时阻塞状态又分为三种:

1)等待阻塞:运行的线程执行wait()方法,JVM会把该线程放入等待池中。
         2)同步阻塞:运行的线程在获取对象的同步锁时,若该同步锁被别的线程占用,则JVM会把该线程放入锁池中。
        
3)其他阻塞:运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入可运行状态。

5.死亡状态:线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

Java多线程学习笔记(一)——多线程实现和安全问题的更多相关文章

  1. Java基础学习笔记: 多线程,线程池,同步锁(Lock,synchronized )(Thread类,ExecutorService ,Future类)(卖火车票案例)

    多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念.进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线 ...

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

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

  3. Android(java)学习笔记216:多线程断点下载的原理(Android实现)

    之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...

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

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

  5. java进阶-多线程学习笔记

    多线程学习笔记 1.什么是线程 操作系统中 打开一个程序就是一个进程 一个进程可以创建多个线程 现在系统中 系统调度的最小单元是线程 2.多线程有什么用? 发挥多核CPU的优势 如果使用多线程 将计算 ...

  6. Android(java)学习笔记159:多线程断点下载的原理(Android实现)

    之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1. 新建一个Android工程: (1)其中我们先实现布 ...

  7. Java IO学习笔记七:多路复用从单线程到多线程

    作者:Grey 原文地址:Java IO学习笔记七:多路复用从单线程到多线程 在前面提到的多路复用的服务端代码中, 我们在处理读数据的同时,也处理了写事件: public void readHandl ...

  8. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  9. 孙鑫VC学习笔记:多线程编程

    孙鑫VC学习笔记:多线程编程 SkySeraph Dec 11st 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified ...

随机推荐

  1. uva 11552 dp

    UVA 11552 - Fewest Flops 一个字符串,字符串每 k 个当作一组,组中的字符顺序能够重组.问经过重组后改字符串能够编程最少由多少块字符组成.连续的一段字符被称为块. dp[i][ ...

  2. Dalvik虚拟机总结

    一.Dalvik虚拟机启动 在启动Zygote进程时,会启动Dalvik虚拟机,完毕以下几件事: 1. 创建了一个Dalvik虚拟机实例: 2. 载入了Java核心类及注冊其JNI方法: 3. 为主线 ...

  3. HDFS学习笔记(2)hdfs_shell &amp; JavaAPI

    FileSystem shell指令 官方文档: HDFS Commands Reference appendToFile cat checksum chgrp chmod chown copyFro ...

  4. 算法竞赛入门经典 习题 2-10 排列(permutation)

    习题 2-10 用1,2,3.....,9组成3个三位数abc.def和ghi,每一个数字恰好使用一次,要求abc:def:ghi=1:2:3.输出全部解. #include <stdio.h& ...

  5. WAMP 2.5 &quot;FORBIDDEN&quot; error

    对于web开发人员来说.远程訪问站点能够非常方便的提高开发站点开发效率,那么在wamp环境下,默认仅仅支持本地訪问,那么怎样訪问开启远程站点訪问呢? 开启方法: wamp2.5(32bit) 集成环境 ...

  6. [Python] partial改变方法默认參数

    Python 标准库中 functools库中有非常多对方法非常有有操作的封装,partial Objects就是当中之中的一个,他是对方法參数默认值的改动. 以下就看下简单的应用測试. #!/usr ...

  7. android TabHost控件

    (一)TabHost控件,默认是在顶部显示的 TabHost是盛放Tab按钮和Tab内容的首要容器, TabWidget(tabs标签)用于选择页面,是指一组包含文本或图标的 ,FrameLayout ...

  8. Git下的冲突解决【转】

    本文转载自:http://www.cnblogs.com/sinojelly/archive/2011/08/07/2130172.html 冲突的产生 很多命令都可能出现冲突,但从根本上来讲,都是m ...

  9. YTU 2774: Prepare for CET6

    2774: Prepare for CET6 时间限制: 1 Sec  内存限制: 128 MB 提交: 40  解决: 37 题目描述 Hard to force the CET4&6 is ...

  10. Android之仿今日头条顶部导航栏效果

    随着时间的推移现在的软件要求显示的内容越来越多,所以要在小的屏幕上能够更好的显示更多的内容,首先我们会想到底部菜单栏,但是有时候像今日头条新闻客户端要显示的内容太多,而且又想在主界面全部显示出来,所以 ...