我们将会从以下的几点理解java线程的一些概念:

一、线程的基本概念
在计算机中有进程和线程这么两个概念,进程中可以有多个线程,它们是从属关系,进程往往更像是资源的占有者,线程才是程序的执行者,多个线程之间共享着进程中的资源。一个cpu同时只能运行一个线程,每个线程都有一个时间片,时间片用完了就会被阻塞并让出CPU的控制权,交给下一个线程使用。这样在计算机中就可以实现多任务的假象,其实CPU在不断的切换线程,好像多个任务在同时运行。
使用线程的优势毋庸置疑,可以增加CPU的执行效率,一旦某个线程需要等待某种资源(例如:等待打印机),就可以将它阻塞释放CPU让CPU执行别的线程,而不需要让CPU和此线程一起等待某种资源从而提高系统效率,另外一点就是可以用这种假象增加用户体验度。但是,CPU在切换不同线程之间所要花费的代价也是不可忽视的,在较为复杂的程序中这种劣势可能九流一毛,但是如果在简单的程序中就会显得尤为突出。
二、创建一个线程
接下来我们看看如何在java中创建一个线程来实现多个线程同时运行。第一种方式,java 中有一个类Thread,我们只要继承这个类并重写他的run方法,调用start方法就可以启动一个新的线程了。(没见过的同学可能不能理解以下代码,下面我会解释)
/*声明自己的一个线程类*/
public class Test_thread extends Thread {
//重写Thread类中的run方法
public void run(){
System.out.println("i am the thread");
}
}
public class Test_Class {
public static void main(String[] args){
Test_thread thread = new Test_thread();
thread.start();
}
}
输出结果:i am the thread
首先我们先了解一下,一个线程被创建之后,怎么才能启动运行,我们调用thread.start();方法启动一个线程,首先就会执行我们重写的run方法(如果没有重写就会调用Thread类的run方法,什么也不做,这也是我们重写run方法的原因),也就是说run方法是一个线程的开始。有个疑问,为什么调用start方法,却执行了run方法了?其实调用start方法就是为线程的启动做准备操作,分配线程私有的堆栈资源,然后执行run方法。
下面我们看创建一个线程的第二种方式,实现接口Runnable,并重写其中的run方法。
public class Test_thread implements Runnable {
public void run(){
System.out.println("i am the thread");
}
}
public class Test_Class {
public static void main(String[] args){
Test_thread thread = new Test_thread();
thread.start();//编译错误
}
}
我们会发现虽然重写了run方法,但是在调用start方法的时候却编译错误,我们进入到Runnable接口的源代码中可以看到,只有一个抽象方法run,所以没有启动线程的start方法,所以我们还是要借助Tread类。
public class Test_Class {
public static void main(String[] args){
Thread thread = new Thread(new Test_thread());
thread.start();
}
}
因为Thread类中有start方法,所以可以使用Thread的一个构造函数传入一个实现了Runnable接口的类型,构建一个Thread类。
三、线程的属性和状态
在一个多线程的程序中我们使用线程的一些属性来区别和辨认它们:
private long tid; private volatile char name[]; public static native Thread currentThread() private boolean daemon = false; private volatile int threadStatus = 0; public final static int NORM_PRIORITY = 5;
每个线程会有一个tid指定此线程的在所有线程中的排序,这个值是递增的,还有一个name指定该线程的名字,也可以使用setName设置一个优雅的线程名字,Thread类还提供了一个方法返回当前正在占用CPU的线程对象。每个线程在某个时刻都是有状态的,属性threadStatus记录了当前对象线程的状态是什么,默认情况下,所有的线程的优先级都被置为5,如果有特殊需要可以修改线程的优先级,使得某个线程可以优先得到运行。下面介绍线程的几种不同的状态。
下面具体的说说不同状态下的线程的一些操作,首先看看new,线程从此被创建,只是离运行状态还需要一些准备。Runnable表示线程是可运行,至于是否已经处于运行状态还要看系统给的时间片是否用完,如果用完了就会将此线程放置在可运行线程队列的尾部,等待下次分配时间片,如果时间片没有用完,就是处于运行状态的(这也是为什么叫做Runnable而不是Running的原因)。接下来的两种状态Blocked和waiting都表示线程阻塞,需要让出CPU。只是导致它们处于这种状态的原因不一样,具体的在我们介绍完synchronized关键字之后就会不言而喻了。
四、关键字synchronized
先看一段代码:
public class Test_thread extends Thread{
public static int count = 0;
public void run(){
try {
Thread.sleep((int) (Math.random() * 100));
}catch(InterruptedException e){
}
count++;
}
}
public class Test_Class {
public static void main(String[] args){
Test_thread[] thread = new Test_thread[1000];
for(int a=0;a<1000;a++){
thread[a] = new Test_thread();
thread[a].start();
}
for(int a=0;a<1000;a++){
try {
thread[a].join();
}catch (InterruptedException e){
}
}
System.out.println(Test_thread.count);
}
}
按照直觉,创建1000个线程,每个线程随机睡觉并将公共变量增一,main线程等待所有线程执行结束之后,输出公共变量的值。按照直觉答案应该是1000,但是我们运行的结果每次都是不一样的,接近1000但每次都不一样。这是为什么呢?这其实就是简单的模拟了高并发,可能有几个线程睡了相同的时间,同时醒来获取的count值是相同的,这就导致这几个线程对count的操作被覆盖了。
public class Test_thread extends Thread{
public static int count = 0;
public void run(){
try {
Thread.sleep((int) (Math.random() * 100));
}catch(InterruptedException e){
}
/*使用关键字*/
synchronized (Test_thread.class){
count++;
}
}
}
一个简单的关键字就可以轻松解决这样的高并发的问题。至于为什么这么写?在介绍完synchronized关键字之后,想必你就会知道了。
首先我们需要知道,每个对象都有一把内部锁。所以被synchronized关键字修饰的方法,其实是被加了内部对象锁。我们看代码:
public class Counter{
private int count;
/*为实例方法加此关键字*/
public synchronized int getCount(){
return count;
}
}
为实例方法添加关键字,实际上就是给当前的对象加锁;括号中就是要加锁的对象。
public class Counter{
private int count;
/*为实例方法加此关键字*/
synchronized(this){
return count;
}
}
对于静态方法,实际上就是为这个类加上锁;
public class Counter{
private static int count;
public static synchronized int getCount(){
return count;
}
}
/*实际上给这个类加上锁*/
public class Counter{
private int count;
synchronized(Counter.class){
return count;
}
}
五、深入理解synchronized的一些特性
第一个性质是:可重入性。被synchronized修饰的方法中的所有操作都是原子操作,但是当我们需要在其中访问另外的一些需要锁的代码时候,可以直接获取别的锁。也就是当前的对象是可以获得多个锁的。
第二个性质是:内存的可见性。在我们的计算机中,其实有很多的操作并不是很"干脆"的,比如你向数据库中存数据时,其实很多时候一些待存入的数据积累在缓存中等到一定数据量的时候才会统一的存入数据库,但是在我们看来这些数据其实应该早就存入数据库了。这就导致了一个内存的不可见性问题。当然我们也是可以使用关键字synchronized来保证每次取出的数据都是最新的。在释放锁的时候会立即将数据协会内存,获得锁的时候会去读取最新的内容。
public class Counter{
private int count;
public synchronized int getCount(){
return count;
}
}
/*每次获得该对象的锁之后,去获取最新的count数值*/
其实,如果仅仅是要保证内存的不可见性,使用synchronized关键字可能代价有点高,在这种情况下,我们可以使用关键字volatile。
public class Counter{
/*使用关键字volatile*/
private volatile int count;
public int getCount(){
return count;
}
}
/*此关键字保证每次使用count的时候数据都是最新的*/
总结
以上就是这篇文章的全部内容了,还是希望大家发现其中错误直接指出,方便我纠正错误,更新知识。java并发系列文章,希望大家多多关注。
# java线程synchronized
# synchronized关键字
# java多线程关键字
# Java的Synchronized关键字学习指南(全面 & 详细)
# 深入分析JAVA Synchronized关键字
# Java synchronized关键字使用方式及特性解析
# Java synchronized关键字和Lock接口实现原理
# Java中synchronized关键字引出的多种锁 问题
# Java多线程并发编程 Synchronized关键字
# 实例解析Java中的synchronized关键字与线程安全问题
# Java中synchronized关键字修饰方法同步的用法详解
# Java多线程编程中synchronized关键字的基础用法讲解
# 详解Java中synchronized关键字的死锁和内存占用问题
# 举例讲解Java中synchronized关键字的用法
# Java多线程之synchronized关键字的使用
# 就会
# 重写
# 多个
# 都是
# 可以使用
# 用完
# 创建一个
# 都有
# 就可以
# 两种
# 中有
# 这就
# 运行状态
# 见性
# 基本概念
# 自己的
# 加锁
# 类中
# 是一个
# 这是
相关文章:
如何用IIS7快速搭建并优化网站站点?
网站好制作吗知乎,网站开发好学吗?有什么技巧?
导航网站建站方案与优化指南:一站式高效搭建技巧解析
学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?
深圳防火门网站制作公司,深圳中天明防火门怎么编码?
如何在阿里云高效完成企业建站全流程?
想学网站制作怎么学,建立一个网站要花费多少?
深圳网站制作的公司有哪些,dido官方网站?
建站VPS选购需注意哪些关键参数?
在线制作视频网站免费,都有哪些好的动漫网站?
如何通过VPS建站实现广告与增值服务盈利?
如何快速搭建高效服务器建站系统?
建站之星安装后如何配置SEO及设计样式?
武汉网站制作费用多少,在武汉武昌,建面100平方左右的房子,想装暖气片,费用大概是多少啊?
如何快速搭建虚拟主机网站?新手必看指南
GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?
实例解析Array和String方法
C#如何在一个XML文件中查找并替换文本内容
如何选择高效响应式自助建站源码系统?
如何获取上海专业网站定制建站电话?
Avalonia如何实现跨窗口通信 Avalonia窗口间数据传递
深圳企业网站制作设计,在深圳如何网上全流程注册公司?
网站制作需要会哪些技术,建立一个网站要花费多少?
如何在阿里云域名上完成建站全流程?
盐城做公司网站,江苏电子版退休证办理流程?
家庭建站与云服务器建站,如何选择更优?
如何打造高效商业网站?建站目的决定转化率
建站主机选择指南:服务器配置与SEO优化实战技巧
攀枝花网站建设,攀枝花营业执照网上怎么年审?
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
香港服务器网站测试全流程:性能评估、SEO加载与移动适配优化
建站之星后台搭建步骤解析:模板选择与产品管理实操指南
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?
建站主机是否属于云主机类型?
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
如何确保西部建站助手FTP传输的安全性?
如何在阿里云虚拟主机上快速搭建个人网站?
整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去?
油猴 教程,油猴搜脚本为什么会网页无法显示?
自助网站制作软件,个人如何自助建网站?
武清网站制作公司,天津武清个人营业执照注销查询系统网站?
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
如何做网站制作流程,*游戏网站怎么搭建?
高端云建站费用究竟需要多少预算?
建站主机选哪种环境更利于SEO优化?
Android自定义listview布局实现上拉加载下拉刷新功能
如何获取开源自助建站系统免费下载链接?
枣阳网站制作,阳新火车站打的到仙岛湖多少钱?
如何制作网站标识牌,动态网站如何制作(教程)?
*请认真填写需求信息,我们会在24小时内与您取得联系。